poj 2752 Seek the Name, Seek the Fame
#include <iostream> //KMP算法
using namespace std;
char A[500000];
int m,P[500000],res[500000];
void get_next()
{
P[1]=0;
int j=0;
for(int i=2;i<=m;++i)
{
while(j>0&&A[j+1]!=A[i])
j=P[j];
if(A[j+1]==A[i])
j=j+1;
P[i]=j;
}
}
int main()
{
while(scanf("%s",A+1)!=EOF)
{
for(m=0;A[m+1]!='\0';++m);
get_next();
int j=m,t=0; //字符串本身的长度毫无疑问符合前后缀的定义
while(j>0)
{
res[++t]=j;
j=P[j];
}
for(int i=t;i>0;--i)
cout<<res[i]<<" ";
cout<<endl;
}
return 0;
}
/*
sample input :ababcababababcabab 2 4 9 18
2是表示字符串前两个元素和后两个元素一样:ab
int j=m,t=0;
while(j>0)
{
res[++t]=j;
j=P[j];
}
下面分析下过程:
第1个循环内:res[1]=18,j=P[18]=9,j=9表示前9个元素和后9个元素相同,即 "ababcabab"
P[18]=9,表示由18个元素组成的这一串"ababcababababcabab"中,满足前后缀相同的最大长度为9
(注意是最大长度,才能把所有的情况全都考虑进来)
第2个循环内:res[2]=9,j=P[9]=4,表示"ababcabab"的前后缀相同的最大长度为4,都为"abab"
由这两步,可知第2个循环内的字符串"ababcabab"前缀"abab"与后缀"abab"相同,
这里的后缀"abab"就是第1个循环内的字符串"ababcababababcabab"的前缀"ababcabab"的最后部分
也就相同于"ababcababababcabab"的后缀的最后部分,
故通过间接相等,使得"abab"同时为原字符串"ababcababababcabab"的前后缀
这样一步步进行下去,直到j==0
*/