​http://poj.org/problem?id=2752​

题目要把所有公共前缀后缀长度求出 那就先求最长的那个 也就是next[l] 然后再找它的公共前缀后缀长度next[next[l]] 即次长的 次次长的

KMP解法

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=4e5+10;

int nxtt[maxn],ans[maxn];
char ch[maxn];

void kmp(char *t,int lt)
{
int i,j;
nxtt[0]=-1;
i=0,j=-1;
while(i<lt)
{
if(j==-1||t[i]==t[j])
{
i++,j++;
nxtt[i]=j;
}
else j=nxtt[j];
}
}

int main()
{
int l,i,tot;
while(scanf("%s",ch)!=EOF)
{
l=strlen(ch);
kmp(ch,l);
i=l,tot=0;
while(i!=0)
{
ans[++tot]=i;
i=nxtt[i];
}
for(i=tot;i>=1;i--)
{
printf("%d",ans[i]);
if(i>1) printf(" ");
else printf("\n");
}
}
return 0;
}

 

EXKMP解法

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e5+10;

int nxtt[maxn],ans[maxn];
int l,tot;
char ch[maxn];

void exkmp(char *t,int lt)
{
int i=0,j,po;
nxtt[0]=lt;//初始化next[0]
while(t[i]==t[i+1]&&i+1<lt)//计算next[1]
i++;
nxtt[1]=i;
po=1;//初始化po的位置
for(i=2;i<lt;i++)
{
if(nxtt[i-po]+i<nxtt[po]+po)//第一种情况,可以直接得到next[i]的值
nxtt[i]=nxtt[i-po];
else//第二种情况,要继续匹配才能得到next[i]的值
{
j=nxtt[po]+po-i;
if(j<0)j=0;//如果i>po+next[po],则要从头开始匹配
while(i+j<lt&&t[j]==t[j+i])//计算next[i]
j++;
nxtt[i]=j;
po=i;//更新po的位置
}
}
}

int main()
{
int t,i;
while(scanf("%s",ch)!=EOF)
{
l=strlen(ch);
exkmp(ch,l);
tot=0;
for(i=l-1;i>=0;i--)
{
if(i+nxtt[i]==l) ans[++tot]=nxtt[i];
}
for(i=1;i<=tot;i++)
{
printf("%d",ans[i]);
if(i<tot) printf(" ");
else printf("\n");
}
}
return 0;
}