POI2012 PRE-Prefixuffix

发布时间:2023年12月21日

P3546 [POI2012] PRE-Prefixuffix

题目大意

对于两个字符串 S 1 , S 2 S_1,S_2 S1?,S2?,如果将 S 1 S_1 S1?的一个后缀移动到开头后这个字符串变成了 S 2 S_2 S2?,则称 S 1 , S 2 S_1,S_2 S1?,S2?循环同构。

给定一个长度为 n n n的字符串 S S S,求满足下面条件的最大的 L L L

  • L L L不超过 n 2 \dfrac n2 2n?
  • S S S长度为 L L L的前缀和 S S S长度为 L L L的后缀循环等价

1 ≤ n ≤ 1 0 6 1\leq n\leq 10^6 1n106


题解

题目要求的就是形如下面这样的前后缀,其中红色部分相同,绿色部分相同。
在这里插入图片描述
判断两个字符串相同可以用哈希。对于每个位置 i i i,我们用 f i f_i fi?表示满足以下条件的的最大的 k k k

  • [ i , i + k ? 1 ] = [ n ? i ? k + 2 , n ? i + 1 ] [i,i+k-1]=[n-i-k+2,n-i+1] [i,i+k?1]=[n?i?k+2,n?i+1]
  • i + k ? 1 ≤ n 2 i+k-1\leq \dfrac n2 i+k?12n?

如果通过枚举 k k k来求每个 f i f_i fi?的话,时间复杂度是 O ( n 2 ) O(n^2) O(n2)的,我们考虑优化。

我们发现, f i ? 1 ≤ f i + 2 f_{i-1}\leq f_i+2 fi?1?fi?+2,证明如下:

假设 f i ? 1 > f i + 2 f_{i-1}>f_i+2 fi?1?>fi?+2,因为 f i ? 1 f_{i-1} fi?1? f i f_i fi?多了 i ? 1 i-1 i?1这个位置,如果将 f i ? 1 f_{i-1} fi?1?对应的绿色部分的第一个字符和最后一个字符去掉,那么一定符合 f i f_i fi?的条件,也就是说 f i f_i fi?至少为 f i ? 1 ? 2 f_{i-1}-2 fi?1??2,推得 f i ? 1 ≤ f i + 2 f_{i-1}\leq f_i+2 fi?1?fi?+2,与 f i ? 1 > f i + 2 f_{i-1}>f_i+2 fi?1?>fi?+2矛盾,得证 f i ? 1 ≤ f i + 2 f_{i-1}\leq f_i+2 fi?1?fi?+2

根据这个条件,我们可以 O ( n ) O(n) O(n)求出所有 f i f_i fi?

然后,对于每个 i i i,判断 [ 1 , i ] [1,i] [1,i] [ n ? i + 1 , n ] [n-i+1,n] [n?i+1,n]是否相同,如果相同就用 i + f i ? 1 i+f_i-1 i+fi??1更新答案。

时间复杂度为 O ( n ) O(n) O(n)

code

#include<bits/stdc++.h>
using namespace std;
const int base=233;
const long long mod=1e9+7;
const int N=1000000;
int n,ans=0,f[N+5];
long long pw[N+5],g[N+5];
char s[N+5];
long long gt(int l,int r){
	return (g[r]-g[l-1]*pw[r-l+1]%mod+mod)%mod;
}
int main()
{
	scanf("%d",&n);
	scanf("%s",s+1);
	pw[0]=1;
	for(int i=1;i<=n;i++){
		g[i]=(g[i-1]*base+s[i]-'a'+1)%mod;
		pw[i]=pw[i-1]*base%mod;
	}
	for(int i=n/2;i>=1;i--){
		f[i]=min(f[i+1]+2,n/2-i+1);
		while(f[i]>0&&gt(i,i+f[i]-1)!=gt(n-i-f[i]+2,n-i+1)) --f[i];
	}
	for(int i=1;i<=n/2;i++){
		if(gt(1,i-1)==gt(n-i+2,n)) ans=max(ans,i+f[i]-1);
	}
	printf("%d",ans);
	return 0;
}
文章来源:https://blog.csdn.net/tanjunming2020/article/details/135134905
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。