*题解:P10271 漫长悄悄话

题目链接

解析

先手玩一下看看 \(\operatorname{LCP}(\operatorname{Rev}(\operatorname{lcs}(i,j)),\operatorname{lcp}(i,j))\) 是什么。首先长度为 \(x\)\(\operatorname{Rev}(\operatorname{lcs}(i,j))\)\(S_i = S_j,S_{i - 1} = S_{j - 1},\dots S_{i - x + 1} = S_{j - x + 1}\);长度为 \(y\)\(\operatorname{lcp}(i,j)\)\(S_i = S_j,S_{i + 1} = S_{j + 1},\dots,S_{i + y - 1} = S_{j + y - 1}\);最后长度为 \(z\)\(\operatorname{LCP}(\operatorname{Rev}(\operatorname{lcs}(i,j)),\operatorname{lcp}(i,j))\)\(S_{i - 1} = S_{i + 1},S_{i - 2} = S_{i + 2},\cdots,S_{i - z + 1} = S_{i + z - 1}\)\(S[i - z + 1,i + z - 1] = S[j - z + 1,j + z - 1]\)

于是可以发现,题目要求的就是出现过至少两次的奇长度回文串的半径。

考虑 Manacher,先求出每个位置能扩展的最大长度。然后由于长的回文串内部包含着短的回文串,所以考虑二分答案对应的回文串长度,按照这个长度遍历整个串,对于可扩展长度大于等于 \(mid\) 的位置求 hash,\(O(\log n)\) 统计是否有重复出现的 hash 值即可。

时间复杂度 \(O(n\log^2 n)\)

代码

/*
*/
#include <bits/stdc++.h>
#define eps 0.0000000001
#define ls(x) ((x) << 1)
#define rs(x) (((x) << 1) | 1)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2e6 + 5,M = 5e5 + 5,P = 2000000,mod1 = 998244353,mod2 = 1e9 + 7,b1 = 131,b2 = 13331;
int len[N];
int h1[N],h2[N],mi1[N],mi2[N];
pii get(int l,int r){
	return make_pair((h1[r] + mod1 - 1ll * h1[l - 1] * mi1[r - l + 1] % mod1) % mod1,(h2[r] + mod2 - 1ll * h2[l - 1] * mi2[r - l + 1] % mod2) % mod2);	
}
int n;
string t;
bool chk(int x){
	vector<pii> v;
	for(int i=2;i<t.size();i += 2)if(t[i] >= 'a' && t[i] <= 'z'){
		if(len[i] >= x){
			v.push_back(get(i - x + 1,i + x - 1));
		}
	}
	sort(v.begin(),v.end());
	for(int i=1;i<v.size();i++){
		if(v[i] == v[i - 1]) return true;
	}
	return false;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	mi1[0] = mi2[0] = 1;
	for(int i=1;i<N;i++){
		mi1[i] = 1ll * mi1[i - 1] * b1 % mod1;
		mi2[i] = 1ll * mi2[i - 1] * b2 % mod2;
	}
	
	cin>>n;
	string s;
	cin>>s;
	t = "!";
	for(int i=0;i<s.size();i++){
		t.push_back('#');
		t.push_back(s[i]);
	}
	t += "#?";
	for(int i=1;i<t.size();i++){
		h1[i] = (1ll * h1[i - 1] * b1 % mod1 + t[i]) % mod1;
		h2[i] = (1ll * h2[i - 1] * b2 % mod2 + t[i]) % mod2;
	}
	int r = 0,c = 0;
	for(int i=2;i<t.size() - 1;i++){
		int p = 0;
		if(r > i){
			p = min(r - i,len[c - (i - c)]);
		}
		while(t[i - p - 1] == t[i + p + 1]) p++;
		if(i + p > r){
			r = i + p;
			c = i;
		}
		len[i] = p;	
	}
	vector<int> num;
	for(int i=1;i<=n;i += 2){
		num.push_back(i);
	}
	int l = 0;r = n / 2;
	int res = 0;
	while(l < r){
		int mid = (l + r + 1) >> 1;
		if(chk(mid * 2 + 1)){
			l = mid;
			res = mid * 2 + 1; 
		}else{
			r = mid - 1;
		}
	}
	if(l == 0 && chk(1)){
		res = 1;
	}
	cout<<(res + 1) / 2;
	return 0;
}
posted @ 2026-06-10 23:57  yutar  阅读(9)  评论(0)    收藏  举报