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 }
洛谷3375

 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 }
bzoj1355

 

posted @ 2017-10-18 21:41  Vincent_hwh  阅读(147)  评论(0编辑  收藏  举报