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

浙公网安备 33010602011771号