KMP Seek the Name,Seek the Fame

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); 
    } 
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值