poj kmp
专题训练ING
今天弄了一天的 KMP ,大且做个总结(poj kmp)。
poj 3167 .3080(另开博文)2752.1961.2406
1961.2406
求一个串能否被其一子串完全不重复覆盖
利用next数组的性质,自我匹配一遍即可,判断i是否整除i-next[i]
1961
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; char s[1000011]; int next[1000011]; int n,i,t,j,x; char c; void Read() { while(c=getchar(),c<'a'||c>'z'); s[++n]=c; while(c=getchar(),c>='a'&&c<='z')s[++n]=c; } int main() { while(true){ scanf("%d",&n); t++; if(n==0)break; n=0; Read(); x=0; for(i=2;i<=n;i++){ while(x!=0&&s[i]!=s[x+1])x=next[x]; if(s[i]==s[x+1])x++; next[i]=x; } printf("Test case #%d\n",t); for(i=2;i<=n;i++){ if(i%(i-next[i])==0&&i/(i-next[i])!=1)printf("%d %d\n",i,i/(i-next[i])); } printf("\n"); } }
2406
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; char s[1000011]; int next[1000011]; bool p; int n,i,j,x; char c; void Read() { while(c=getchar(),c!='.'&&(c<'a'||c>'z')); if(c=='.')p=false; s[++n]=c; while(c=getchar(),c>='a'&&c<='z')s[++n]=c; } int main() { while(true){ p=true; n=0; Read(); if(p==false)break; memset(next,0,sizeof(next)); x=0; for(i=2;i<=n;i++){ while(x!=0&&s[i]!=s[x+1])x=next[x]; if(s[i]==s[x+1])x++; next[i]=x; } if(n%(n-next[n])!=0)printf("1\n"); else printf("%d\n",n/(n-next[n])); } }
2752
不断next..
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; char s1[400011],s[400011]; int next[400011]; int n,i,j,x,t; int ans[400011]; int main() { while(scanf("%s",&s)!=EOF){ n=strlen(s); for(i=1;i<=n;i++)s1[i]=s[i-1]; x=0; for(i=2;i<=n;i++){ while(x!=0&&s1[i]!=s1[x+1])x=next[x]; if(s1[i]==s1[x+1])x++; next[i]=x; } t=0; x=n; while(x!=0){ ans[++t]=x; x=next[x]; } for(i=t;i>=2;i--)printf("%d ",ans[i]); printf("%d\n",ans[1]); } }