POJ 2752 Seek the Name, Seek the Fame(KMP的Next数组应用)

题目链接:http://poj.org/problem?id=2752

Description

The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the little cat to give names to their newly-born babies. They seek the name, and at the same time seek the fame. In order to escape from such boring job, the innovative little cat works out an easy but fantastic algorithm: 

Step1. Connect the father's name and the mother's name, to a new string S. 
Step2. Find a proper prefix-suffix string of S (which is not only the prefix, but also the suffix of S). 

Example: Father='ala', Mother='la', we have S = 'ala'+'la' = 'alala'. Potential prefix-suffix strings of S are {'a', 'ala', 'alala'}. Given the string S, could you help the little cat to write a program to calculate the length of possible prefix-suffix strings of S? (He might thank you by giving your baby a name:) 

Input

The input contains a number of test cases. Each test case occupies a single line that contains the string S described above. 

Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000. 

Output

For each test case, output a single line with integer numbers in increasing order, denoting the possible length of the new baby's name.

Sample Input

ababcababababcabab
aaaaa

Sample Output

2 4 9 18
1 2 3 4 5

题目大意:找出给定串所有前后缀匹配串长度并从小到大输出

题目思路:

Next数组应用,通过KMP求出到的Next[len](假设等于一个x)肯定是前后缀匹配的串,假设前缀是s1,后缀是s2,且长度都为x,那么下一个长度就是s1和s2的前后缀匹配了,但是s1和s2是一样的,对吧,所以就相当于s1的前后缀匹配了,即Next[x]就是下一个前后缀匹配长度了。则可通过Next数组的回滚来获取答案。

代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<map>

using namespace std;

#define FOU(i,x,y) for(int i=x;i<=y;i++)
#define FOD(i,x,y) for(int i=x;i>=y;i--)
#define MEM(a,val) memset(a,val,sizeof(a))
#define PI acos(-1.0)

const double EXP = 1e-9;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const ll MINF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
const int N = 1e6+5;

char mo[N];
int Next[N];
int ans[N];

void Get_next()
{
    int i,j;
    j = Next[0] = -1;
    i = 0;
    int len = strlen(mo);
    while(i<len)
    {
        while(j!=-1&&mo[i]!=mo[j])
            j = Next[j];
        Next[++i]  = ++j;
    }
}

void solve()
{
    Get_next();
    int len = strlen(mo);
    //for(int i=0;i<=len;i++)
    //   printf("%d ",Next[i]);
    int cnt=0;
    ans[++cnt] = len;
    int t = len;
    while(1)
    {
        t = Next[t];
        if(t==0)
            break;
        ans[++cnt] = t;

    }
    for(int i=cnt;i>=1;i--)
        printf("%d%c",ans[i],(i==1)?'\n':' ');
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    std::ios::sync_with_stdio(false);
    while(~scanf(" %s",&mo))
    {
        solve();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值