kmp
题意:
分析:
我们看着一题,我们仔细想想。首先如果没有要求中间 子串 的话,就很简单了。我们直接输出前后缀相等的就好了。
无论是 kmp 还是 暴力 都是线性时间。
但是麻烦就在于中间要有字串。
那我们想想,如何判断中间有没有子串呢?
假设,next[n] = k 意味着s0,s1,s2,s3,s4.....sk-1 == sn-k+1,sn-k+2.....sn
子串即为s[0:k] 那么如何判断中间有没有子串呢?
如果有子串,s[i:i+k]那么我肯定s[0:i+k]的next就会是k
想想是不是这样?
也就是说我们求next数组就可以了。
求出next[n]看next[n]的值一共被取了几次。
如果一次以上,那么我们就return s[0:next[n]]
否则,我们就看next[next[n]],只要这不为-1那就是正确答案。
为-1则不可能。
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
const int max_n = 1e6 + 100;
int n;
int net[max_n];
void getnext(string p) {
net[0] = -1;register int i = 0, j = -1;
while (i < p.size()) {
if (j == -1 || p[i] == p[j]) { net[++i] = ++j; }
else j = net[j];
}
}
int res[max_n];
int main() {
ios::sync_with_stdio(0);
string s;cin >> s;
getnext(s);
for (register int i = 1;i < s.size();++i)
++res[net[i]];
int ans = net[s.size()];
if (ans <= 0)
cout << "Just a legend\n";
else if (res[ans])
cout << s.substr(0, ans) << endl;
else if (net[ans] > 0)
cout << s.substr(0, net[ans]) << endl;
else
cout << "Just a legend\n";
}
京公网安备 11010502036488号