CF126B Password题解
考虑去掉出现在中间的条件之后,如何枚举一个字符串的公共前后缀。
发现跳 \(nxt\) 数组就可以。用 \(x\) 表示当前公共前后缀,这样循环一下.
while(nxt[x]) {
x = nxt[x] //枚举出每一个公共前后缀,也就是可能成为答案的串
}
然后考虑如何判断出现在中间的条件。其实我们就是要寻找一个最大的 \(x\),使得存在 \(nxt_i = nxt_x\) \((i\in [2, n - 1])\)。
那你就存一下 \(nxt_i\) \((i\in [2, n - 1])\) 呗,跳到哪判一下。
#include <bits/stdc++.h>
#define m_p(x, y) make_pair(x, y)
#define pb(x) push_back(x)
#define int long long
#define ull unsigned long long
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define rep_(i, a, b) for(int i = a; i >= b; --i)
using namespace std;
namespace FYH {
constexpr int N = 1e6 + 5;
int n, nxt[N], vis[N];
string s;
inline void main() {
cin >> s;
n = s.size();
s = "$" + s;
int j = 0;
rep(i, 2, n) {
while(s[i] != s[j + 1] && j) {
j = nxt[j];
}
if(s[i] == s[j + 1]) {
++j;
}
nxt[i] = j;
if(i != n) {
vis[nxt[i]]++;
}
}
/*核心代码只有下面这一小段*/
int x = n;
while(nxt[x]) {
if(vis[nxt[x]]) {
rep(i, 1, nxt[x]) {
cout << s[i];
}
return;
}
x = nxt[x];
}
cout << "Just a legend";
}
}
signed main() {
ios :: sync_with_stdio(0), cin.tie(0);
int t = 1;
//cin >> t;
while(t--) {
FYH :: main();
}
return 0;
}

浙公网安备 33010602011771号