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 }