P3546 PRE-Prefixuffix Sol

这题挺妙的。

有两个串 A,BABBA 一定循环同构。

利用这个性质可以解决这道题目。

fi 表示使得 A=s1...i,B=si+1...i+x 成立的最大 x

因为原串的 border A 很好找,所以寻找中间 B 的关系。

考虑如何转移,观察 fifi+1

考虑一个字符 c,有 AcBcBA 循环同构,A 对应 [1,i]

此时除去首、尾的串 cB...cB 仅剩 B...cB1...lenb1

那么原来的 border 为 |cB|=lenb+1,现在的 border 为 lenb1

这是最劣情况,也就是说,fi+1fi2

那么就维护一个指针实时统计答案即可。

指针移动次数至多为 2n,复杂度正确。

最后再判一下 A 是否合法即可计算答案。

注意哈希卡自然溢出。

#include <bits/stdc++.h>
using ll = long long;
using namespace std;

const int N = 1e6 + 10;
const ll bas = 131, Mod = 998244353; int n, dp[N];
ll hsh[N], pw[N]; char str[N];

inline ll qry(int l, int r) {
	return (hsh[r] - hsh[l - 1] * pw[r - l + 1] % Mod + Mod) % Mod;
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(0), cout.tie(0);
	cin >> n; for (int i = 1; i <= n; ++i) cin >> str[i];
	pw[0] = 1; for (int i = 1; i <= n; ++i) pw[i] = pw[i - 1] * bas % Mod;
	for (int i = 1; i <= n; ++i) hsh[i] = (hsh[i - 1] * bas + str[i]) % Mod;
	for (int len = n / 2; len; --len) {
		dp[len] = dp[len + 1] + 2;
		while (dp[len] + len > n / 2) --dp[len];
		while (dp[len] && qry(len + 1, len + dp[len]) != qry(n - len - dp[len] + 1, n - len)) --dp[len];
	}
	int res = 0;
	for (int i = 1; i <= n / 2; ++i)
		if (qry(1, i) == qry(n - i + 1, n)) res = max(res, i + dp[i]);
	cout << res << endl;
	return 0;
}
posted @   MistZero  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示