Seek the Name,Seek the Fame
时间限制: 1 Sec 内存限制: 128 MB
题目描述
给定一个字符串s,从小到大输出s中既是前缀又是后缀的子串的长度。
字符串长度不超过四十万
输入
输入包含许多测试数据。 每个测试数据为包含上述字符串S的单行。
限制:输入中只能出现小写字母。 1 <= S的长度<= 400000。
输出
对于每个数据,从小到大给出整数,每个整数代表既是前缀又是后缀的子串的长度
样例输入
ababcababababcabab
aaaaa
样例输出
2 4 9 18
1 2 3 4 5
联想到KMP算法的next数组。这道题就可做了。
首先我们得明白,next[j]是表示除了p[j]之外,0~j-1这个串,前缀和后缀的最大匹配长度
而且,对于任意一个满足条件的前缀,它最后一个字符肯定与整个字符串的最后一个字符相同。假设现在有位置k使[1,k][1,k]满足条件,那么显然[1,nextk][1,nextk]仍然满足条件,并且,由于next[]是最长的公共前后缀,所以不存在某满足条件的前缀长度大于nextknextk小于kk。
我们从k=n开始,一直k = next[k]迭代下去,遇到s[k]==s[n]就记录答案,到k=0时为止。这样我们就把答案从大到小记录下来了。逆序输出即可。
最后再输出一个len就行`
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int nxt[400005];
int ans[400005];
char ch[400005];
int cnt,len;
void gnxt(){
nxt[0]=-1;
int i=0,j=-1;
while(i<len){
if(j==-1||ch[i]==ch[j]){
++i;
++j;
nxt[i]=j;
}
else j=nxt[j];
}
}
int main()
{
while(cin>>ch){
len=strlen(ch);
gnxt();
cnt=0;
int t=nxt[len-1];
while(t!=-1){
if(ch[t]==ch[len-1])ans[cnt++]=t+1;
t=nxt[t];
}
for(int i=cnt-1;i>=0;--i){
printf("%d ",ans[i]);
}
printf("%d\n",len);
}
}