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