[POI2012] PRE-Prefixuffix 题解

题目传送门

思路

按照题目的定义,两个循环同构的字符串可以表示成 \(\texttt{AB,BA}\)

那么 \(s\) 可以表示为 \(\texttt{ABSBA}\)

\(f_i\) 表示 \(\texttt{A}\)\(s_1\sim s_i\)\(\texttt{B}\) 的最大长度。那么就有 \(f_i\le f_{i+1}+2\)

所以每次先把 \(f_i\) 赋值为 \(f_{i+1}+2\),如果 \(f_i+i>\lfloor \frac{n}2\rfloor\),那么 \(f_i\) 就赋值为 \(\lfloor \frac{n}2\rfloor-i\)

接下来一点一点减小 \(f_i\),直到两边相同。

最后统计答案,枚举 \(\texttt{A}\) 的长度,如果两边 \(\texttt{A}\) 相同,那么 \(ans = \max\{ans,f_i+i\}\)。最后输出即可。

:判断两段字符串是否相同用哈希即可。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e7+5,base = 13331,mod = 1e9+7;
int n,h[N],p[N],f[N],ans;
string s;
int get(int l,int r)
{
	return (h[r]-h[l-1]*p[r-l+1]%mod+mod)%mod;
}
bool ok(int l1,int r1,int l2,int r2)
{
	return get(l1,r1)==get(l2,r2);
}
signed main()
{
	cin>>n>>s;
	s = ' '+s;
	for(int i = 1;i<=n;i++)
		h[i] = (h[i-1]*base+s[i])%mod;
	p[0] = 1;
	for(int i = 1;i<=n;i++)
		p[i] = p[i-1]*base%mod;
	for(int i = n/2;i;i--)
	{
		f[i] = f[i+1]+2;
		if(f[i]+i>n/2) f[i] = n/2-i;
		while(f[i]&&(!ok(i+1,i+f[i],n-i-f[i]+1,n-i))) f[i]--;
	}
	for(int i = 1;i<=n/2;i++)
		if(ok(1,i,n-i+1,n))
			ans = max(ans,f[i]+i);
	cout<<ans;
	return 0;
}
posted @ 2024-04-08 16:40  pyy1  阅读(37)  评论(0)    收藏  举报