POJ 2752 Seek the Name, Seek the Fame(KMP求公共前后缀)

题目链接:http://poj.org/problem?id=2752

题目大意:给你一串字符串s找到所有的公共前后缀,即既是前缀又是后缀的子串。

解题思路:

如图所示

 

假设字符串pi与jq为符合条件的一组公共前后缀,那么易得pi=jq,如下图所示

若在字符串pi内,pk1与k2i为公共前后缀,有因为pi=jq所以对应的k2i在字符串jq内有后缀k4q与其等价。所以pi内的公共前后缀等也是pq的公共前后缀,而i=next[q],显然是个递归。

所以,可以通过不断使pos=next[pos]进行递归求出所有的公共前后缀。这里其实利用了一些next[]数组的对称性质。

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<map>
 5 #include<string>
 6 using namespace std;
 7 const int N=1e6+5;
 8 
 9 int m;
10 int nxt[N],ans[N];
11 char p[N];
12 
13 void getnext(){
14     int i,j;
15     i=0,j=nxt[0]=-1;
16 
17     while(i<m){
18         while(j!=-1&&p[i]!=p[j])
19             j=nxt[j];
20         nxt[++i]=++j;
21     }
22 }
23 
24 int main(){
25     while(~scanf("%s",p)){
26         m=strlen(p);
27         getnext();
28         int cnt=0;
29         ans[cnt++]=m;
30         int t=m;
31         while(t!=-1){
32             if(nxt[t]>0)
33                 ans[cnt++]=nxt[t];
34             t=nxt[t];
35         }
36         for(int i=cnt-1;i>=0;i--){
37             printf("%d%c",ans[i],i==0?'\n':' ');
38         }
39     }
40     return 0;
41 }

 

posted @ 2018-03-01 23:55  Yeader  阅读(722)  评论(0编辑  收藏  举报