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;
}