发现双倍回文串一定是中心是#
的回文串。
所以考虑枚举#
点。发现以(i)为中心的双倍回文的左半部分是个回文串,其中心一定位于(i-frac{pal[i]-1}2)到(i-1)之间,而且越远越好。所以我们用一个(set)来存一下目前为止回文右端点(geq i)的点,然后在(set)中找到大于等于(i-frac{pal[i]-1}2)的最小值即可。
#include<bits/stdc++.h>
using namespace std;
#define fec(i,x,y) (int i=head[x],y=g[i].to;i;i=g[i].ne,y=g[i].to)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
#define isin(x,S) (((S)>>((x)-1))&1)
#define fi first
#define se second
#define pb push_back
template<typename I>inline void read(I&x){int f=0,c;while(!isdigit(c=getchar()))c=='-'?f=1:0;x=c&15;while(isdigit(c=getchar()))x=(x<<1)+(x<<3)+(c&15);f?x=-x:0;}
template<typename A,typename B>inline char SMAX(A&a,const B&b){return a<b?a=b,1:0;}
template<typename A,typename B>inline char SMIN(A&a,const B&b){return a>b?a=b,1:0;}
typedef long long ll;typedef unsigned long long ull;typedef pair<int,int>pii;
const int N=500000+7;
int n,pal[N<<1],ans;char a[N],s[N<<1];
inline void Manacher(){
int p=0,pos=0;
for(int i=1;i<=n;++i){
if(p>i)pal[i]=min(p-i+1,pal[(pos<<1)-i]);else pal[i]=1;
while(s[i+pal[i]]==s[i-pal[i]])++pal[i];
if(SMAX(p,i+pal[i]-1))pos=i;
}
}
set<int>t;
vector<int>p[N<<1];
int main(){
#ifdef hzhkk
freopen("hkk.in","r",stdin);
#endif
scanf("%d%s",&n,a+1);
s[0]=s[1]='#';
for(int i=1;i<=n;++i)s[i<<1]=a[i],s[i<<1|1]='#';
n=n<<1|1;
Manacher();
for(int i=1;i<=n;i+=2){
t.insert(i);
if(i+pal[i]-1<=n)p[i+pal[i]-1].pb(i);
if(i&1)SMAX(ans,(i-*t.lower_bound(i-(pal[i]-1)/2))*2);
for(vector<int>::iterator j=p[i].begin();j!=p[i].end();++j)t.erase(*j);
for(int i=1;i<=n;++i)
}
printf("%d
",ans);
}