一句话原题:给出两个字符串ST,问T在S中最早出现的位置。
next数组的求法
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int next[2000000]; 5 char s[2000000],p[2000000]; 6 7 void Getnext() 8 { 9 int len=strlen(p); 10 next[0]=-1; 11 int k=-1,j=0; 12 while(j<len-1)//注意下标 13 { 14 //p[k]表示前缀,p[j]表示后缀 15 if(k==-1||p[j]==p[k]) 16 { 17 k++;j++; 18 if(p[j]!=p[k]) 19 next[j]=k; 20 else//因为不能出现p[j] = p[ next[j ]],所以当出现时需要继续递归,k = next[k] = next[next[k]] 21 next[j]=next[k]; 22 } 23 else k=next[k]; 24 } 25 } 26 27 int kmp() 28 { 29 int i=0,j=0; 30 int lens=strlen(s),lenp=strlen(p); 31 while(i<lens&&j<lenp) 32 { 33 if(j==-1||s[i]==p[j]) 34 { 35 i++; 36 j++; 37 } 38 else j=next[j];//相当于模式串向右移动 39 } 40 return j==lenp?i-j:-1;?//如果全部搜过了,返回搜到的起始的点 41 } 42 43 int main() 44 { 45 46 scanf("%s%s",s,p); 47 Getnext(); 48 cout<<kmp()+1<<endl;//因为下标是从0开始的 49 return 0; 50 }
时间复杂度: 我们发现如果某个字符匹配成功,模式串首字符的位置保持不动,仅仅是i++、j++;如果匹配失配,i 不变(即 i 不回溯),模式串会跳过匹配过的next [j]个字符。整个算法最坏的情况是,当模式串首字符位于i - j的位置时才匹配成功,算法结束。
所以,如果文本串的长度为n,模式串的长度为m,那么匹配过程的时间复杂度为O(n),算上计算next的O(m)时间,KMP的整体时间复杂度为O(m + n)。
我也不是弄得很清楚,所以很多都没有写完全,如果看不懂,可以在下面留言~