题意:给定一个长度为n的字符串,求它每个前缀的最短循环节
分析:KMP的失配函数有一个特点,i表示前i个字符,若i%(i-f[i])==0,则前i个字符,最短循环节的长度为i-f[i]。。
// File Name: 1328.cpp // Author: zlbing // Created Time: 2013/3/17 19:22:33 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,n) for(int i=0;i<n;i++) #define REP1(i,n) for(int i=1;i<n+1;i++) const int MAXN=1e6+10; char ch[MAXN]; int f[MAXN]; void getFail(char *p,int *f){ int m=strlen(p); f[0]=f[1]=0; for(int i=1;i<m;i++){ int j=f[i]; while(j&&p[i]!=p[j])j=f[j]; f[i+1]=p[i]==p[j]?j+1:0; } } void find(char *T,char *p,int *f){ int n=strlen(T); int m=strlen(p); getFail(p,f); int j=0; for(int i=0;i<n;i++){ while(j&&p[j]!=T[i])j=f[j]; if(p[j]==T[i])j++; if(j==m)printf("%d\n",i-m+1); } } int main(){ int n; int cas=0; while(~scanf("%d",&n)) { if(!n)break; scanf("%s",ch); printf("Test case #%d\n",++cas); getFail(ch,f); for(int i=2;i<=n;i++){ if(f[i]&&i%(i-f[i])==0)printf("%d %d\n",i,i/(i-f[i])); } printf("\n"); } return 0; }