P4287 [SHOI2011]双倍回文 - manacher


题解

CSP 考前做道 manacher。

一个性质:一个字符串的本质不同回文子串个数是 \(\mathcal{O}(n)\) 级别的。

于是枚举这 \(\mathcal{O}(n)\) 个回文子串,逐个判断即可。

具体枚举方式见代码。

代码

#include 
#include 
#include 
#include 
using namespace std;
#define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
#define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
template void Read(T &_x){
	_x=0;int _f=1;
	char ch=getchar();
	while(!isdigit(ch)) _f=(ch=='-'?-1:_f),ch=getchar();
	while(isdigit(ch)) _x=_x*10+(ch^48),ch=getchar();
	_x*=_f;
}
typedef long long ll;
const int N=1e6+5;
int n,len[N];
char s[N];
int main(){
	Read(n);n=0;
	char ch=getchar();
	while(!isalpha(ch)) ch=getchar();
	s[++n]='#';
	while(isalpha(ch)){
		s[++n]=ch,s[++n]='#';
		ch=getchar();
	}
	int ans=0;
	for(int l=0,r=0,i=1;i<=n;++i){
		len[i]=(i<=r?min(r-i+1,len[l+r-i]):1);
		while(i-len[i]>0&&s[i-len[i]]==s[i+len[i]]) ++len[i];
		if(i+len[i]-1>r){
			if(i%2){
				for(int j=max(i+4,r);j<=i+len[i]-1;++j){
					if((j-i)%4==0&&len[i-(j-i)/2]>(j-i)/2) ans=max(ans,j-i); 
				}
			}
			r=i+len[i]-1,l=i-len[i]+1;
		}
	}
	printf("%d\n",ans);
	return 0;
}