poj 2752 Seek the Name, Seek the Fame

Seek the Name, Seek the Fame

 POJ - 2752 

题目大意:输入一串全为小写字母的字符串,字符串长度小于400000,输出所有满足前缀和后缀相等的字符的长度,这个”组合条件“我会在样例中说明。

第一组样例解释:

样例一:ababcababababcabab  2:ababcababababcabab  4:ababcabababcabab  9:ababcabab ababcabab 18: 全部

思路:

next数组的使用

下面给出描述: (i>1)[下标从0开始] 
next[i]的意义就是:前面长度为i的字串的【前缀和后缀的最大匹配长度】 

那么这题怎么利用这个性质呢? 

详细分析一下:【就用上面的第一个例子说明吧】 

a  b  a  b  c  a  b  a  b  a  b  a  b  c  a  b  a  b

0  0  1  2  0  1  2  3  4  3  4  3  4  5  6  7  8  9

len2 = 18    next[len2] = 9 
说明对于前面长度为18的字符串,【长度为9的前缀】和【长度为9的后缀】是匹配的, 即上图的蓝色跟红色匹配 
也就是整个串的最大前后缀匹配长度就是9了 
所以接下来根本不需要考虑长度大于9的情况啦 

好了!既然现在只需考虑长度小于9的前后缀匹配情况,那么 
[问题就转化成蓝色串的前缀跟红色串的后缀的匹配问题了!!! 
又因为蓝串==红串 
所以问题又转化成 
找蓝串自己的前缀跟自己的后缀的最大匹配了!!! 

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 400010
using namespace std;
int ans[maxn],nxt[maxn],l,cnt;
char s[maxn];
void getnxt(){
    int i=0,j=-1;
    nxt[0]=-1;
    while(i!=l){
        if(s[i]==s[j]||j==-1)nxt[++i]=++j;
        else j=nxt[j];
    }
}
int main(){
    while(scanf("%s",s)!=EOF){
        l=strlen(s);cnt=0;
        ans[++cnt]=l;
        getnxt();
        int pos=l;
        while(1){
            if(nxt[pos]==0)break;
            ans[++cnt]=nxt[pos];
            pos=nxt[pos];
        }
        for(int i=cnt;i>=1;i--)printf("%d ",ans[i]);
        puts("");
    }
}

 

 


posted @ 2017-12-23 08:50  Echo宝贝儿  阅读(130)  评论(0编辑  收藏  举报