KMP
最近效率不高不低吧,在写usaco的题,然而真的很水==也没什么可以放上来的东西
边复习一下其他模板
KMP
http://www.matrix67.com/blog/archives/115
利用i,j两个指针检索两个字符串:s1[i-j+1..i]==s2[1..j]
s1[i+1]!=s2[j+1],失配
next[j]应该是所有满足s2[1..next[j]]=s2[j-next[j]+1..j]的最大值
对s2预处理出next数组,在失配时直接跳到next[i]位
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=1001000; 6 const int maxm=1001000; 7 char s1[maxn],s2[maxm]; 8 int next[maxm],n,m; 9 int main(){ 10 scanf("%s%s",s1+1,s2+1); 11 n=strlen(s1+1),m=strlen(s2+1); 12 int j=0; 13 memset(next,0,sizeof(next)); 14 for (int i=2;i<=m;i++){ 15 while (j>0&&s2[j+1]!=s2[i]) j=next[j]; 16 if (s2[j+1]==s2[i]) j++; 17 next[i]=j; 18 } 19 j=0; 20 for (int i=1;i<=n;i++){ 21 while (j>0&&s2[j+1]!=s1[i]) j=next[j]; 22 if (s2[j+1]==s1[i]) j++; 23 if (j==m){ 24 printf("%d\n",i-j+1); 25 j=next[j]; 26 } 27 } 28 for (int i=1;i<=m;i++) 29 printf("%d ",next[i]); 30 return 0; 31 }
next数组的应用:n-next[n]为最小循环节长度
http://www.cnblogs.com/jackge/archive/2013/01/05/2846006.html
n/(n-next[n])表示循环节重复次数,不是整数时最后一个循环节残缺。
特别注意next[i]=0的情况,此时循环节默认判定为自身,要特判为否。
循环长度:while(next[i]>0&&i%(i-f[i])==0) printf("%d %d\n",i,i/(i-next[i]));
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int maxn=1000100; 5 int n,next[maxn]; 6 char s[maxn]; 7 int main(){ 8 scanf("%d%s",&n,s+1); 9 int j=0; 10 memset(next,0,sizeof(next)); 11 for (int i=2;i<=n;i++){ 12 while (j>0&&s[j+1]!=s[i]) j=next[j]; 13 if (s[j+1]==s[i]) j++; 14 next[i]=j; 15 } 16 printf("%d\n",n-next[n]); 17 return 0; 18 }