Codeforces 126B

题意:给出一个字符串,要求从中分别找出一个前缀、中缀、后缀,使得他们相等。找出满足要求的长度最大的子串,否则输出Just a legend


KMP+Hash。KMP的next数组的本质为模式串的当前位置前缀中,最长匹配的前后缀数量。
那么就枚举串中每一个位置,通过next数组可以得到一个前缀和一个中缀,这样再比较这个前缀和含相同数量字符的后缀是否相等。
时间复杂度为O(n)

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

unsigned int base[maxn];
unsigned int h[maxn];
int Next[maxn];
char s[maxn];
int slen;

void init_hash()
{
    int MAGIC = 3;
    h[0] = 0;
    for(int i = 1; i <= slen; i++){
        h[i] = h[i-1] * MAGIC + s[i-1];
    }
    base[0] = 1;
    for(int i = 1; i <= slen; i++)
        base[i] = base[i-1]*MAGIC;
}

unsigned int string_hash(int l, int r){
    return h[r] - h[l]*base[r-l];
}

void getNext()
{
    Next[0] = -1;
    int k = -1, j = 0;
    while(j < slen){
        if(k == -1 || s[j] == s[k]){
            k++, j++;
            Next[j] = k;
        }
        else k = Next[k];
    }
}

int main()
{
    scanf("%s", s);
    slen = strlen(s);
    init_hash();
    getNext();

    int curlen = 0;
    for(int i = 1; i < slen-1; i++){
        if(Next[i+1]==0) continue;
        if(string_hash(0, Next[i+1]) == string_hash(slen-Next[i+1], slen) && curlen < Next[i+1])
            curlen = Next[i+1];
    }
    if(curlen != 0) printf("%s\n",s+slen-curlen);
    else printf("Just a legend\n");
    return 0;
}
posted @ 2017-07-17 22:47  />.<\  阅读(276)  评论(0编辑  收藏  举报