P4287 [SHOI2011]双倍回文 - manacher
题解
CSP 考前做道 manacher。
一个性质:一个字符串的本质不同回文子串个数是 \(\mathcal{O}(n)\) 级别的。
于是枚举这 \(\mathcal{O}(n)\) 个回文子串,逐个判断即可。
具体枚举方式见代码。
代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
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<typename T> 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;
}
Written by Alan_Zhao