對於匹配一個字符串是否爲另外一個字符串的子串,傳統的算法是先從頭比較,當遇到不等時在回溯過去,從第二個字母開始匹配,kmp算法就是能夠消除回溯,提升效率。PS:KMP爲三老外的名字縮寫。web
KMP算法大意:設s爲目標串(主串),t爲模式串,並設i指針和j指針分別指示目標串和模式串中正待比較的字符,令i和j的初值都爲零。如有si=tj,則i和j分別加1;不然,i不變,j退回到j=next[j]的位置(即模式串右滑),比較si和tj,若相等則指針各加1,不然j再退回到下一個j=next[j]位置(即模式串繼續右滑),再比較si和tj。以此類推,直到出現下列兩種狀況之一:一種是j退回到某個j=next[j]位置時有si=tj,則指針各加1後繼續匹配;另外一種是j退回到j=-1時,此時令i,j指針各加1,即下一次比較s(i+1)和t0。算法
next[j]數組:此數組主要針對模式串,next[j]表示的是在模式串中第j個字符前面最大的前綴與後綴相等(並不是是對稱)的長度,如「abcac」中,next[0]=-1(第一個爲方便代碼通常都設爲-1),next[1]=next[2]=next[3] =0,next[4]=1(由於有a=a)。PS:重點數組
例題:spa
Period指針
Time Limit: 3000MS | Memory Limit: 30000K | |
Total Submissions: 13155 | Accepted: 6167 |
Descriptioncode
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 AK ,that is A concatenated K times, for some string A. Of course, we also want to know the period K.orm
Inputip
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.字符串
Outputget
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 a
Sample Input
3 nd the period K separated by a single space; the prefix sizes must be in increasing order. Print a blank line after each test case.
aaa 12 aabaabaabaab 0
Sample Output
Test case #1 2 2 3 3 Test case #2 2 2 6 2 9 3 12 4
題目大意:給你若干個字符串,判斷該字符串的前n位最多重複了幾回,好比,給ababab,結果是前4位重複了2次,前6位重複了3次。
CODE:
#include<stdio.h>#include<string.h>#define maxlen 1000001char str[maxlen];int next[maxlen];void get_next()//求next數組{ int j=0,k=-1,l=strlen(str); next[0]=-1; while(j<l) { if(k==-1||str[j]==str[k]) { j++; k++; next[j]=k; } else k=next[k]; } return;}int main(){ int n,len,i,test=0; while(scanf("%d",&n)&&n) { getchar(); gets(str); get_next(); printf("Test case #%d\n",++test); for(i=2; i<=n; i++) //求出前i個字符中重複串 { len=i-next[i]; if(i%len==0&&i/len>1) printf("%d %d\n",i,i/len); } printf("\n"); } return 0;}KMP算法複雜度爲O(m+n),普通法爲O(m*n)。