题目链接:传送门
题目描述:
给你一串字符串S,要你找出它的最长子串t,满足这个t既是S的前缀和后缀,也要在串S的中间位置出现过。如果没有,输出“Just a legend”,否则输出这个子串。
题目分析:
遇到这题时,刚学完后缀数组,又有后缀出现,就以为是后缀数组了。然后看了下时间1e6,时间刚刚好。然后就高高兴兴的去打了出来,可能常数太大了吧,T了。后来,听大佬讲是KMP,嗯。。。。。。。我还是太菜了。好吧,这题考的是KMP种next数组的运用,先用vis数组把next数组的值记录一遍(除了最后一个),然后用一个while循环看vis[next[i]].如果非零,答案的长度就是next[i]了,否则,i=next[i].
代码:
#include<bits/stdc++.h>
using namespace std;
string s;
int len, knext[1000006], vis[1000006] = {0};
void KMP(){
len = s.length();
int i, j;
j = -1, i = 0;
knext[0] = -1;
while(i<len){
if(j == -1 || s[i] == s[j]) knext[++i] = ++j;
else j = knext[j];
}
knext[0] = 0;
for(i=0;i<len;++i) vis[knext[i]]++;
int flag = 0;
i = len;
while(knext[i]){
if(vis[knext[i]]){
for(j=0;j<knext[i];++j) printf("%c", s[j]);
printf("\n");
flag = 1;
break;
}
else i = knext[i];
}
if(!flag) cout << "Just a legend" << endl;
}
int main()
{
cin >> s;
KMP();
return 0;
}