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 }

 

posted @ 2018-03-02 00:24  Yeader  阅读(181)  评论(0编辑  收藏  举报