KMP算法模板

90 篇文章 0 订阅
5 篇文章 0 订阅

例题1链接:点击打开链接

原题:

Oulipo
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 24044 Accepted: 9633

Description

The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from the book:

Tout avait Pair normal, mais tout s’affirmait faux. Tout avait Fair normal, d’abord, puis surgissait l’inhumain, l’affolant. Il aurait voulu savoir où s’articulait l’association qui l’unissait au roman : stir son tapis, assaillant à tout instant son imagination, l’intuition d’un tabou, la vision d’un mal obscur, d’un quoi vacant, d’un non-dit : la vision, l’avision d’un oubli commandant tout, où s’abolissait la raison : tout avait l’air normal mais…

Perec would probably have scored high (or rather, low) in the following contest. People are asked to write a perhaps even meaningful text on some subject with as few occurrences of a given “word” as possible. Our task is to provide the jury with a program that counts these occurrences, in order to obtain a ranking of the competitors. These competitors often write very long texts with nonsense meaning; a sequence of 500,000 consecutive 'T's is not unusual. And they never use spaces.

So we want to quickly find out how often a word, i.e., a given string, occurs in a text. More formally: given the alphabet {'A''B''C', …, 'Z'} and two finite strings over that alphabet, a word W and a textT, count the number of occurrences of W in T. All the consecutive characters of W must exactly match consecutive characters of T. Occurrences may overlap.

Input

The first line of the input file contains a single number: the number of test cases to follow. Each test case has the following format:

  • One line with the word W, a string over {'A''B''C', …, 'Z'}, with 1 ≤ |W| ≤ 10,000 (here |W| denotes the length of the string W).
  • One line with the text T, a string over {'A''B''C', …, 'Z'}, with |W| ≤ |T| ≤ 1,000,000.

Output

For every test case in the input file, the output should contain a single number, on a single line: the number of occurrences of the word W in the text T.

Sample Input

3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN

Sample Output

1
3
0

Source


AC  code:


#include<stdio.h>

#include<string.h>
char p[1111111],t[1111111];
int next[1111111],lenp,lent;
void get()
{
int i,j;
i=0;
next[i]=-1;
j=-1;
while(i<=lenp)
{
if(j==-1||p[i]==p[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int main()
{
int i,j,cas,cnt;
while(scanf("%d",&cas)!=EOF)
{
while(cas--)
{
scanf("%s",p);
scanf("%s",t);
lenp=strlen(p);
lent=strlen(t);
get();
i=-1;
j=-1;
cnt=0;
while(i<=lent)
{
if(j==-1||p[j]==t[i])
{
i++;
j++;
}
else
j=next[j];
if(j==lenp)
{
j--;
i--;
j=next[j];
cnt++;
}
}
printf("%d\n",cnt);
}
}
return 0;

}


提取模板:


void Get_next()
{
int i=0,j=-1;
next[0]=-1;
while(i<=Tlen)
{
if(j==-1||chT[i]==chT[j])
{
i++; j++;
next[i]=j;
}
else 
j=next[j];
}
}


int Kmp(int u)
{
int i=u-1,j=-1,m=0;     //字符串从0开始存储的
while(i<=TTlen)
{
if(j==-1||ch[i]==chT[j])
{
i++; j++;
}
else
j=next[j];
if(j>=Tlen)         //**注意这里要j--,i++,因为上面匹配成功了i和j的值加多了1
{
m++;
j--; i--;
j=next[j];      //返回
}
}
return m;
}


例题2链接:点击打开链接


原题:


Theme Section

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1239    Accepted Submission(s): 646


Problem Description
It's time for music! A lot of popular musicians are invited to join us in the music festival. Each of them will play one of their representative songs. To make the programs more interesting and challenging, the hosts are going to add some constraints to the rhythm of the songs, i.e., each song is required to have a 'theme section'. The theme section shall be played at the beginning, the middle, and the end of each song. More specifically, given a theme section E, the song will be in the format of 'EAEBE', where section A and section B could have arbitrary number of notes. Note that there are 26 types of notes, denoted by lower case letters 'a' - 'z'.

To get well prepared for the festival, the hosts want to know the maximum possible length of the theme section of each song. Can you help us?
 

Input
The integer N in the first line denotes the total number of songs in the festival. Each of the following N lines consists of one string, indicating the notes of the i-th (1 <= i <= N) song. The length of the string will not exceed 10^6.
 

Output
There will be N lines in the output, where the i-th line denotes the maximum possible length of the theme section of the i-th song.
 

Sample Input
  
  
5 xy abc aaa aaaaba aaxoaaaaa
 

Sample Output
  
  
0 0 1 1 2
 

Source


AC  code:


#include<stdio.h>
#include<string.h>
char s[1111111];
int next[1111111],len,ans[1111111];
void get()
{
int i,j;
i=0;
next[0]=-1;
j=-1;
while(i<=len)
{
if(j==-1||s[j]==s[i])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int main()
{
int i,j,k,cas,fg;
while(scanf("%d",&cas)!=EOF)
{
while(cas--)
{
scanf("%s",s);
len=strlen(s);
get();
ans[0]=len;
i=0;j=len;
while(next[j]>0)
{
ans[++i]=next[j];
j=next[j];
}
fg=0;
for(j=0;j<=i;j++)
{
if(ans[j]>len/3)
continue;
else
{
for(k=2*ans[j];k<=len-ans[j];k++)
{
if(next[k]==ans[j])
{
fg=1;
printf("%d\n",ans[j]);
break;
}
}
}
if(fg)
break;
}
if(fg==0)
printf("0\n");
}
}
return 0;
}



提取模板:

void Get_next()       //求字符串的next[]前缀数组  
{  
    int i=0,j=-1;  
    next[0]=-1;  
    while(i<=Tlen)  
    {  
        if(j==-1||ch[i]==ch[j])  
        {  
            i++; j++;  
            next[i]=j;  
        }  
        else  
            j=next[j];  
    }  
}  

例题3链接:点击打开链接


原题:



Blue Jeans
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 12324 Accepted: 5355

Description

The Genographic Project is a research partnership between IBM and The National Geographic Society that is analyzing DNA from hundreds of thousands of contributors to map how the Earth was populated. 

As an IBM researcher, you have been tasked with writing a program that will find commonalities amongst given snippets of DNA that can be correlated with individual survey information to identify new genetic markers. 

A DNA base sequence is noted by listing the nitrogen bases in the order in which they are found in the molecule. There are four bases: adenine (A), thymine (T), guanine (G), and cytosine (C). A 6-base DNA sequence could be represented as TAGACC. 

Given a set of DNA base sequences, determine the longest series of bases that occurs in all of the sequences.

Input

Input to this problem will begin with a line containing a single integer n indicating the number of datasets. Each dataset consists of the following components:
  • A single positive integer m (2 <= m <= 10) indicating the number of base sequences in this dataset.
  • m lines each containing a single base sequence consisting of 60 bases.

Output

For each dataset in the input, output the longest base subsequence common to all of the given base sequences. If the longest common subsequence is less than three bases in length, display the string "no significant commonalities" instead. If multiple subsequences of the same longest length exist, output only the subsequence that comes first in alphabetical order.

Sample Input

3
2
GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
3
GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA
GATACTAGATACTAGATACTAGATACTAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA
GATACCAGATACCAGATACCAGATACCAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA
3
CATCATCATCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
ACATCATCATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACATCATCATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

Sample Output

no significant commonalities
AGATAC
CATCATCAT

Source


AC  code:

#include<stdio.h>
#include<string.h>
char s[11][70],t[70],t1[70];
int next[70],len,cnt;
void get_next(char p[],int lenp)
{
int i,j;
i=0;
next[0]=-1;
j=-1;
while(i<=lenp)
{
if(j==-1||p[i]==p[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int kmp(char s[],int lens,char p[],int lenp)
{
get_next(p,lenp);
int i,j,start;
start=-1;
i=-1;
j=-1;
while(i<=lens)
{
if(j==-1||p[j]==s[i])
{
i++;
j++;
}
else
j=next[j];
if(j==lenp)
{
start=i-lenp+1;//求出在目标字符串中从第几个开始就完全匹配,找不到为-1
break;
}
}
return start;
}
int main()
{
int cas,n,i,j,k,m,c,st,maxlen;
while(scanf("%d",&cas)!=EOF)
{
while(cas--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%s",s[i]);
}
len=strlen(s[1]);
maxlen=0;
for(i=0;i<len-1;i++)
{
for(c=1;c<=len-1-i;c++)
{
j=len-c;
if(j-i+1<maxlen)
break;
cnt=0;
for(m=i;m<=j;m++)
{
t[cnt]=s[1][m];
cnt++;
}
t[cnt]='\0';
for(k=2;k<=n;k++)
{
st=kmp(s[k],len,t,cnt);
if(st==-1)
break;
}
if(k==n+1)
{
if(cnt==maxlen)
{
if(strcmp(t,t1)<0)
strcpy(t1,t);
}
if(cnt>maxlen)
{
maxlen=cnt;
strcpy(t1,t);
}
}
}
}
if(maxlen<3)
printf("no significant commonalities\n");
else
puts(t1);
}
}
return 0;
}


KMP算法模板:

void get_next(char p[],int lenp)
{
int i,j;
i=0;
next[0]=-1;
j=-1;
while(i<=lenp)
{
if(j==-1||p[i]==p[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int kmp(char s[],int lens,char p[],int lenp)
{
get_next(p,lenp);
int i,j,start;
start=-1;
i=-1;
j=-1;
while(i<=lens)
{
if(j==-1||p[j]==s[i])
{
i++;
j++;
}
else
j=next[j];
if(j==lenp)
{
start=i-lenp+1;//求出在目标字符串中从第几个开始就完全匹配,找不到为-1
break;
}
}
return start;
}


例题4链接:点击打开链接


原题:


Corporate Identity
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 5078 Accepted: 1885

Description

Beside other services, ACM helps companies to clearly state their “corporate identity”, which includes company logo but also other signs, like trademarks. One of such companies is Internet Building Masters (IBM), which has recently asked ACM for a help with their new identity. IBM do not want to change their existing logos and trademarks completely, because their customers are used to the old ones. Therefore, ACM will only change existing trademarks instead of creating new ones.

After several other proposals, it was decided to take all existing trademarks and find the longest common sequence of letters that is contained in all of them. This sequence will be graphically emphasized to form a new logo. Then, the old trademarks may still be used while showing the new identity.

Your task is to find such a sequence.

Input

The input contains several tasks. Each task begins with a line containing a positive integer N, the number of trademarks (2 ≤ N ≤ 4000). The number is followed by N lines, each containing one trademark. Trademarks will be composed only from lowercase letters, the length of each trademark will be at least 1 and at most 200 characters.

After the last trademark, the next task begins. The last task is followed by a line containing zero.

Output

For each task, output a single line containing the longest string contained as a substring in all trademarks. If there are several strings of the same length, print the one that is lexicographically smallest. If there is no such non-empty string, output the words “IDENTITY LOST” instead.

Sample Input

3
aabbaabb
abbababb
bbbbbabb
2
xyz
abc
0

Sample Output

abb
IDENTITY LOST

Source



AC  code:


#include<stdio.h>
#include<string.h>
char s[4001][201],s1[201],ans[201];
int next[201],lens[4001];
void get(char p[],int lenp)
{
int i,j;
i=0;
next[0]=-1;
j=-1;
while(i<=lenp)
{
if(j==-1||p[i]==p[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int kmp(char t[],int lent,char p[],int lenp)
{
get(p,lenp);
int i,j,start;
i=-1;j=-1;start=-1;
while(i<=lent)
{
if(j==-1||p[j]==t[i])
{
i++;
j++;
}
else
j=next[j];
if(j==lenp)
{
start=i-lenp+1;
break;
}
}
return start;
}
int main()
{
int n,i,j,k,m,minlen,mini,cnt,st,maxlen;
while(scanf("%d",&n)!=EOF&&n)
{
minlen=300;
for(i=1;i<=n;i++)
{
scanf("%s",&s[i]);
lens[i]=strlen(s[i]);
if(minlen>lens[i])
{
minlen=lens[i];
mini=i;
}
}
maxlen=0;
for(i=0;i<=minlen-2;i++)
{
for(j=1;j<=minlen-i;j++)
{
if(minlen-j-i+1<maxlen)
break;
cnt=0;
for(k=i;k<=minlen-j;k++)
{
s1[cnt++]=s[mini][k];
}
s1[cnt]='\0';
for(m=1;m<=n;m++)
{
if(m==mini)
continue;
st=kmp(s[m],lens[m],s1,cnt);
if(st==-1)
break;
}
if(m==n+1)
{
if(maxlen==cnt)
{
if(strcmp(ans,s1)>0)
strcpy(ans,s1);
}
if(maxlen<cnt)
{
maxlen=cnt;
strcpy(ans,s1);
}
}
}
}
if(maxlen==0)
printf("IDENTITY LOST\n");
else
puts(ans);
}
return 0;
}


例题5链接:点击打开链接


原题:


Power Strings
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 32616 Accepted: 13602

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

Hint

This problem has huge input, use scanf instead of cin to avoid time limit exceed.

Source


该题代码和分析转自网址:http://blog.csdn.net/qq7366020/article/details/12968747

题目大意:   给出一个由某个串重复有限次得到的字符串

                  求重复次数最多是多少,既找出最小重复子串

解题思路:    字符串abcabcabc的next[ ]值为
                   0  1  2  3  4  5  6  7  8  9
                   a  b  c  a  b  c  a  b  c
                  -1  0  0  0  1  2  3  4  5  6
                  假设主串为abcabcabcX,模式串为abcabcabcK,Kmp的匹配过程
                  匹配到第10个字符发现不符:
                  a  b  c  a  b  c  a  b  c  X
                  a  b  c  a  b  c  a  b  c  K
                  不符合,j=next[j]
                  a  b  c  a  b  c  a  b  c  X
                              a  b  c  a  b  c  a  b  c  K
                  不符合,j=next[j]
                  a  b  c  a  b  c  a  b  c  X
                                          a  b  c  a  b  c  a  b  c  K;

                  由next数组的定义可得: S[0-2]=S[3-5]=S[6-8]

                  当且仅当len%(len-next[len])=0时,len-next[len]是字符串的最小循环节

代码:

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #define MAX 1000005  
  4. char ch[MAX];  
  5. int next[MAX];  
  6.   
  7. int Get_next(int Tlen)  
  8. {  
  9.     int i=0,j=-1;  
  10.     next[0]=-1;  
  11.     while(i<Tlen)  
  12.     {  
  13.         if(j==-1||ch[i]==ch[j])  
  14.         {  
  15.             i++; j++;  
  16.             next[i]=j;  
  17.         }  
  18.         else  
  19.             j=next[j];  
  20.     }  
  21.     i=Tlen-j;        //**  
  22.     if(Tlen%i==0)          //**  
  23.         return Tlen/i; //**  
  24.     return 1;  
  25. }  
  26.   
  27. int main()  
  28. {  
  29.     int Tlen;  
  30.     while(scanf("%s",ch)!=EOF)  
  31.     {  
  32.         if(ch[0]=='.')  
  33.             break;  
  34.         Tlen=strlen(ch);  
  35.         printf("%d\n",Get_next(Tlen));  
  36.     }  
  37.     return 0;  
  38. }  
例题6链接: 点击打开链接


原题:

Period
Time Limit: 3000MS Memory Limit: 30000K
Total Submissions: 13365 Accepted: 6296

Description

For each prefix of a given string S with N characters (each character has an ASCII code between 97 and 126, inclusive), we want to know whether the prefix is a periodic string. That is, for each i (2 <= i <= N) we want to know the largest K > 1 (if there is one) such that the prefix of S with length i can be written as A K ,that is A concatenated K times, for some string A. Of course, we also want to know the period K.

Input

The input consists of several test cases. Each test case consists of two lines. The first one contains N (2 <= N <= 1 000 000) – the size of the string S.The second line contains the string S. The input file ends with a line, having the 
number zero on it.

Output

For each test case, output "Test case #" and the consecutive test case number on a single line; then, for each prefix with length i that has a period K > 1, output the prefix size i and the period K separated by a single space; the prefix sizes must be in increasing order. Print a blank line after each test case.

Sample Input

3
aaa
12
aabaabaabaab
0

Sample Output

Test case #1
2 2
3 3

Test case #2
2 2
6 2
9 3
12 4

Source


code:

#include<stdio.h>
#include<string.h>
char s[1000111];
int next[1000111],ans[1000111];
void get(char p[],int lenp)
{
int i,j;
i=0;
j=-1;
next[0]=-1;
while(i<=lenp)
{
if(j==-1||p[j]==p[i])
{
i++;
   j++;
   next[i]=j;
}
else
j=next[j];
}
for(i=1;i<=lenp-1;i++)
{
if((i+1)%(i+1-next[i+1])==0&&(i+1)!=(i+1-next[i+1]))//由于不输出1
printf("%d %d\n",i+1,(i+1)/(i+1-next[i+1]));
}
}
int main()
{
int len,n,cas;
cas=0;
while(scanf("%d",&n)!=EOF&&n)
{
cas++;
scanf("%s",s);
len=strlen(s);
printf("Test case #%d\n",cas);
get(s,len);
printf("\n");
}
return 0;
}


例题7链接:http://poj.org/problem?id=2752


原题:

Seek the Name, Seek the Fame
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 12266 Accepted: 6032

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

Source


下面一部分来自博客:http://blog.csdn.net/hackbuteer1/article/details/7319115

大意:
给出一个字符串A,求A有多少个前缀同时也是后缀,从小到大输出这些前缀的长度。

分析:KMP
对于长度为len的字符串,由next的定义知:
A[0]A[1]...A[next[len]-1]=A[len-next[len]]...A[len-1]此时A[0]A[1]...A[next[len]-1]为一个符合条件的前缀
有A[0]A[1]....A[next[next[len]]-1] = A[len-next[next[len] - next[next[len]]]...A[next[len]-1],故A[0]A[1]....A[next[next[len]]-1]也是一个符合条件的前缀
故从len=>next[len]=>next[next[len]] ....=>直到某个next[]为0均为合法答案,注意当首位单词相同时,也为答案。



code:

#include<string.h>
#include<stdio.h>
char s[400111];
int next[400111],ans[400111],len;
void get(char p[],int lenp)
{
int i,j;
i=0;j=-1;
next[0]=-1;
while(i<=lenp)
{
if(j==-1||p[j]==p[i])
{
i++;j++;
next[i]=j;
}
else
j=next[j];
}
}
int main()
{
int n,cnt,i;
while(scanf("%s",s)!=EOF)
{
len=strlen(s);
get(s,len);
        ans[1]=len;
cnt=1;
n=next[len];
while(n)
{
cnt++;
ans[cnt]=n;
n=next[n];
}
for(i=cnt;i>=1;i--)
printf("%d ",ans[i]);
printf("\n");
}
return 0;
}

解题思路分析亦可参考网址:http://www.doc88.com/p-997525236064.html


例题8链接:点击打开链接


原题:

Cyclic Nacklace

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2870    Accepted Submission(s): 1324


Problem Description
CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, without any surprise, there are only 99.9 yuan left. he is too distressed and thinking about how to tide over the last days. Being inspired by the entrepreneurial spirit of "HDU CakeMan", he wants to sell some little things to make money. Of course, this is not an easy task.

As Christmas is around the corner, Boys are busy in choosing christmas presents to send to their girlfriends. It is believed that chain bracelet is a good choice. However, Things are not always so simple, as is known to everyone, girl's fond of the colorful decoration to make bracelet appears vivid and lively, meanwhile they want to display their mature side as college students. after CC understands the girls demands, he intends to sell the chain bracelet called CharmBracelet. The CharmBracelet is made up with colorful pearls to show girls' lively, and the most important thing is that it must be connected by a cyclic chain which means the color of pearls are cyclic connected from the left to right. And the cyclic count must be more than one. If you connect the leftmost pearl and the rightmost pearl of such chain, you can make a CharmBracelet. Just like the pictrue below, this CharmBracelet's cycle is 9 and its cyclic count is 2:

Now CC has brought in some ordinary bracelet chains, he wants to buy minimum number of pearls to make CharmBracelets so that he can save more money. but when remaking the bracelet, he can only add color pearls to the left end and right end of the chain, that is to say, adding to the middle is forbidden.
CC is satisfied with his ideas and ask you for help.
 

Input
The first line of the input is a single integer T ( 0 < T <= 100 ) which means the number of test cases.
Each test case contains only one line describe the original ordinary chain to be remade. Each character in the string stands for one pearl and there are 26 kinds of pearls being described by 'a' ~'z' characters. The length of the string Len: ( 3 <= Len <= 100000 ).
 

Output
For each case, you are required to output the minimum count of pearls added to make a CharmBracelet.
 

Sample Input
  
  
3 aaa abca abcde
 

Sample Output
  
  
0 2 5
 

Author
possessor WC
 

Source

code:

#include<stdio.h>
#include<string.h>
char s[100111];
int next[100111],len;
void get(char p[],int lenp)
{
int i,j;
i=0;
j=-1;
next[0]=-1;
while(i<=lenp)
{
if(j==-1||p[j]==p[i])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int main()
{
int n,i,j;
while(scanf("%d",&n)!=EOF)
{
while(n--)
{
scanf("%s",s);
len=strlen(s);
get(s,len);
       if(len%(len-next[len])==0)
{
if(next[len]==0)//相当于len/(len-next[len])==1的情况
printf("%d\n",len);
else
printf("0\n");
}
else
{
i=len%(len-next[len])-1;
j=len-1;
while(i>=0)
{
if(s[i]==s[j])
{
i--;
j--;
}
else
break;
}
if(i==-1)
printf("%d\n",len-next[len]-len%(len-next[len]));
else
   printf("%d\n",len);
}
}
}
return 0;
}

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

题目反思与总结:

当所给字符串中无循环节时,如abcdeab , 我们求出其next数组的对应值(注意按照标准的next数组要多求一位,计算时向后推一位计算,因为标准的next数组第n个数表示的是第n-1个字符的匹配情况),然后用字符串长度L-next[L]即可,此时上例中显然next[L]为2,即为多出的ab,所以循环节就是7-2=5;


当所给字符串中有多个字符串时,如abxabxabxab,此时next[L]为8,11-8=3,亦是循环节,我们可以看出L-next[L]就是循环节,其实在一个多个循环节的字符串中,除了第一个循环节中字符外,其他每个位置的下标n-next[n]都是循环节(第一个循环节中的最后一个位置也可)。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林下的码路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值