FZU 1901 Period II(KMP循环节+公共前后缀)
题目链接:http://acm.fzu.edu.cn/problem.php?pid=1901
题目大意:题目大意求出所有p满足s[i]=s[i+p](i<=len-p)
解题思路:
其实就是要找出所有的循环节(不只是最小的),
循环节本质跟公共前后缀有关,可以通过递归的方法求出所有公共前后缀ti,那么len-ti就是相应循环节。
之前写的计算最小循环节,累加循环节得到前缀的方法是有问题的,过不了下面这种数据。
数据:abacaba
结果应该是4,6,7
而求出来的是4,7。因为忽略了除了最小循环节外的其他循环节。
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=1e6+5; 7 8 int len; 9 int nxt[N],ans[N]; 10 char p[N]; 11 12 void getnext(){ 13 int i=0,j=nxt[0]=-1; 14 while(i<len){ 15 while(j!=-1&&p[i]!=p[j]) 16 j=nxt[j]; 17 nxt[++i]=++j; 18 } 19 } 20 21 int main(){ 22 int t,cas=0; 23 scanf("%d",&t); 24 while(t--){ 25 scanf("%s",p); 26 len=strlen(p); 27 getnext(); 28 int t=nxt[len]; 29 int cnt=0; 30 while(t!=-1){ 31 if(t>=0) ans[cnt++]=len-t; 32 t=nxt[t]; 33 } 34 printf("Case #%d: %d\n",++cas,cnt); 35 for(int i=0;i<cnt;i++){ 36 printf("%d%c",ans[i],i==cnt-1?'\n':' '); 37 } 38 } 39 return 0; 40 }