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

posted @ 2026-05-19 16:39  風月華  阅读(6)  评论(0)    收藏  举报