1. 程式人生 > >POJ 2752 Seek the Name, Seek the Fame(KMP求公共前後綴)

POJ 2752 Seek the Name, Seek the Fame(KMP求公共前後綴)

字符串 iostream 字符 org 所有 對稱性 char can for

題目鏈接: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 }

POJ 2752 Seek the Name, Seek the Fame(KMP求公共前後綴)