KMP題目

A - Sum Problem
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

Homer: Marge, I just figured out a way to discover some of the talents we weren’t aware we had. 
Marge: Yeah, what is it? 
Homer: Take me for example. I want to find out if I have a talent in politics, OK? 
Marge: OK. 
Homer: So I take some politician’s name, say Clinton, and try to find the length of the longest prefix 
in Clinton’s name that is a suffix in my name. That’s how close I am to being a politician like Clinton 
Marge: Why on earth choose the longest prefix that is a suffix??? 
Homer: Well, our talents are deeply hidden within ourselves, Marge. 
Marge: So how close are you? 
Homer: 0! 
Marge: I’m not surprised. 
Homer: But you know, you must have some real math talent hidden deep in you. 
Marge: How come? 
Homer: Riemann and Marjorie gives 3!!! 
Marge: Who the heck is Riemann? 
Homer: Never mind. 
Write a program that, when given strings s1 and s2, finds the longest prefix of s1 that is a suffix of s2.

Input

Input consists of two lines. The first line contains s1 and the second line contains s2. You may assume all letters are in lowercase.

Output

Output consists of a single line that contains the longest string that is a prefix of s1 and a suffix of s2, followed by the length of that prefix. If the longest such string is the empty string, then the output should be 0. 
The lengths of s1 and s2 will be at most 50000.

Sample Input

clinton
homer
riemann
marjorie

Sample Output

0
rie 3


對話都是廢話,只看最後一句when given strings s1 and s2, finds the longest prefix of s1 that is a suffix of s2.馬上就想到把s2接到s1後面成爲一個新的字符串,然後找next[n]就完了,我看到很多博客還去找s1前綴和找s2的後綴,然後來匹配,感覺好麻煩。是我太機智(但是並沒有覺得想到這個方法很巧妙)還是他們太死板?

代碼:

#include<stdio.h>
#include<string.h>

#define MaxSize 500005
#define inf 0x3f3f3f3f
#define LL long long int

char s[2*MaxSize],s2[MaxSize];
int next[2*MaxSize];
int n;

void get_next()
{
  int i=0;
  int j=next[0]=-1;

  while(i<n)
    {
      if(j==-1 || s[j]==s[i])
        next[++i]=++j;

      else j=next[j];
    }
}

int main()
{
  while(~scanf("%s%s",s,s2))
    {
      int len=strlen(s);

      s[len]='A';
      s[len+1]='\0';
      /*爲了防止接在一起之後出現一種神奇的情況,中間必須加上一個字符隔開。比如s1:abca,s2:bcab,
      正確答案應該是ab。但如果直接接到一起變成了abcabcab,相同前後綴就變成了abcab,這樣前綴都超過s1的長度明顯就不行了。
      所以中間應加一個字母隔開防止越界(題上說了給的s1和s2只有小寫字母,於是我們就用大寫字母隔),
      變成abcaAbcab,這樣就絕對不會出現前後綴越界的情況了*/

      strcat(s,s2);

      n=strlen(s);

      get_next();

      s[next[n]]='\0';//用for輸出%c多半會超時,這裏手動加個結束符,給出地址用%s輸出速度會快很多

      printf("%s",s);

      if(next[n]!=0) printf(" ");

      printf("%d\n",next[n]);
    }

  return 0;
}








C - 親和串
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

人隨着歲數的增長是越大越聰明還是越大越笨,這是一個值得全世界科學家思考的問題,同樣的問題Eddy也一直在思考,因爲他在很小的時候就知道親和串如何判斷了,但是發現,現在長大了卻不知道怎麼去判斷親和串了,於是他只好又再一次來請教聰明且樂於助人的你來解決這個問題。 
親和串的定義是這樣的:給定兩個字符串s1和s2,如果能通過s1循環移位,使s2包含在s1中,那麼我們就說s2 是s1的親和串。 

Input

本題有多組測試數據,每組數據的第一行包含輸入字符串s1,第二行包含輸入字符串s2,s1與s2的長度均小於100000。 

Output

如果s2是s1的親和串,則輸出"yes",反之,輸出"no"。每組測試的輸出佔一行。 

Sample Input

AABCD
CDAA
ASD
ASDF

Sample Output

yes
no


思路:

既然可以循環匹配,就把原串首尾連接。比如原串是abcd,我們就abcd+abc變成abcdabc,這樣循環問題就解決了。但是如果目標串是bcdab,這樣在連接後的新串裏面是找得到的,感覺是合法的。但是在原串中循環匹配的時候這是不合法的,因爲出現了後面又走到了b,已經開始重疊了。解決這個問題很簡單,判斷如果目標串長度大於原串,就一定找不到。要能在原串中循環匹配成功,長度必定是小於等於原串長度的。


代碼;

#include<stdio.h>
#include<string.h>

#define MaxSize 100005
#define inf 0x3f3f3f3f
#define LL long long int

char s[MaxSize],s1[2*MaxSize],s2[MaxSize];
int next[MaxSize];
int n,m;

void get_next()
{
  int i=0;
  int j=next[0]=-1;

  while(i<m)
    {
      if(j==-1 || s2[i] == s2[j])
        next[++i]=++j;

      else
        j=next[j];
    }
}

void find()
{
  int i=0;
  int j=0;

  while(i<n)
    {
      if(j==-1 || s1[i]==s2[j])
        {
          i++;
          j++;
        }

      else
        j=next[j];

      if(j==m)
        {
          printf("yes\n");
          return;
        }
    }

  printf("no\n");
}

int main()
{
  while(~scanf("%s%s",s,s2))
    {
      strcpy(s1,s);
      strcat(s1,s);

      n=strlen(s1)-1;
      s1[n]='\0';

      m=strlen(s2);

      if(m > strlen(s))
      {
          printf("no\n");
          continue;
      }

      get_next();

      find();
    }

  return 0;
}



F - Seek the Name, Seek the Fame
Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu

Description

The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the little cat to give names to their newly-born babies. They seek the name, and at the same time seek the fame. In order to escape from such boring job, the innovative little cat works out an easy but fantastic algorithm: 

Step1. Connect the father's name and the mother's name, to a new string S. 
Step2. Find a proper prefix-suffix string of S (which is not only the prefix, but also the suffix of S). 

Example: Father='ala', Mother='la', we have S = 'ala'+'la' = 'alala'. Potential prefix-suffix strings of S are {'a', 'ala', 'alala'}. Given the string S, could you help the little cat to write a program to calculate the length of possible prefix-suffix strings of S? (He might thank you by giving your baby a name:) 

Input

The input contains a number of test cases. Each test case occupies a single line that contains the string S described above. 

Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000. 

Output

For each test case, output a single line with integer numbers in increasing order, denoting the possible length of the new baby's name.

Sample Input

ababcababababcabab
aaaaa

Sample Output

2 4 9 18
1 2 3 4 5

思路:

這道題就是把所有的相同前後綴長度輸出來,就是把原來的只求最大next[n]變成了 求長度從0~next[n]的相同前後綴。於是在next[]求到最後一步的時候,對j=next[j]不斷進行迭代就行了。


代碼:

#include <stdio.h>
#include <string.h>
#include <stack>
#include <iostream>
using namespace std;

#define MaxSize 400005

int n;
int next[MaxSize];
char s[MaxSize];

void get_next()
{
  int i=0;
  int j=next[0]=-1;
  stack<int>sta;

  while(i<n)
    {
      if(j==-1 || s[i]==s[j])
        {
            next[++i] = ++j;

            if(i==n)
            {
                i--;
                j--;

                while(j!=-1)
                {
                    if(s[i]==s[j])
                    sta.push(j+1);

                    j=next[j];
                }

                while(!sta.empty())
                {
                    printf("%d ",sta.top());
                    sta.pop();
                }

                printf("%d\n",n);

                break;
            }
        }

      else
        j=next[j];
    }
}

int main()
{
  while(~scanf("%s",s))
    {
      n=strlen(s);

      get_next();
    }
  return 0;
}









E - Power Strings
Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu

Description

Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = "" (the empty string) and a^(n+1) = a*(a^n).

Input

Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.

Output

For each s you should print the largest n such that s = a^n for some string a.

Sample Input

abcd
aaaa
ababab
.

Sample Output

1
4
3




遇到‘.’就停止,傻狍子出題人咋不寫出來,還以爲是不小心多打的句號,坑的一筆。這道題就是求字符串由多少個相同的最小cell組成,這個代碼的思路我想到過,但是不知道是不是真的可行,都準備放棄了,結果看了別人的博客真的可以這樣。


代碼:

#include <stdio.h>
#include <string.h>
#include <stack>
#include <iostream>
using namespace std;

#define MaxSize 1000005

char s[MaxSize];
short next[MaxSize];
int n;

void get_next()
{
  int i=0;
  int j=next[0]=-1;

  while(i<n)
    {
      if(j==-1 || s[i]==s[j])
        next[++i]=++j;

      else
        j=next[j];
    }

  //int len = n-next[n];//告訴你們一件可怕的事,這樣寫的要wa的。明明是和下面那句等價的,但是它就要wa,就是不知道爲什麼,真可怕。
  int len = i-j;


  if(n%len == 0)
    printf("%d\n",n/len);

  else
    printf("1\n");
}

int main()
{
  while(~scanf("%s",s) && strcmp(s,".")!=0)
    {
      n=strlen(s);

      get_next();
    }

  return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章