​http://acm.hdu.edu.cn/showproblem.php?pid=5371​

直接暴力也可以过 不理解 还是线段树优化

对每个偶数回文中心 求出回文半径 只要两个回文中心互相在对方回文半径范围之内 那就是一个题目要求的串

然后用 回文中心+回文半径=最远到达距离 建立线段树 然后从左到右扫一遍 对每个位置 看自己左边回文半径内能覆盖自己的最远即最小的回文中心位置 找到后作差即为所求

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;

int maxx[4*maxn];
int ary[2*maxn],book[2*maxn];
int n;

void manacher(int *ary,int n)
{
int i,p,r;
p=0,r=0;
for(i=0;i<n;i++)
{
if(i<r) book[i]=min(book[2*p-i],r-i);
else book[i]=1;
while(0<=i-book[i]&&i+book[i]<n&&ary[i-book[i]]==ary[i+book[i]]) book[i]++;
if(r<=i+book[i]) p=i,r=i+book[i];
}
}

void build(int l,int r,int cur)
{
int m;
if(l==r)
{
maxx[cur]=l+book[l];
return;
}
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
maxx[cur]=max(maxx[2*cur],maxx[2*cur+1]);
}

void query(int pl,int pr,int pos,int &res,int l,int r,int cur)
{
int m;
//printf("*%d %d %d %d %d %d*\n",pl,pr,pos,l,r,maxx[cur]);
if(pl<=l&&r<=pr)
{
if(maxx[cur]<pos) return;
if(l==r)
{
//printf("*%d %d %d %d %d*\n",pl,pr,l,r,maxx[cur]);
res=l;
}
else
{
m=(l+r)/2;
if(res==-1) query(pl,pr,pos,res,l,m,2*cur);
if(res==-1) query(pl,pr,pos,res,m+1,r,2*cur+1);
}
return;
}
m=(l+r)/2;
if(res==-1&&pl<=m) query(pl,pr,pos,res,l,m,2*cur);
if(res==-1&&pr>m) query(pl,pr,pos,res,m+1,r,2*cur+1);
}

void show(int l,int r,int cur)
{
int m;
//printf("*%d %d %d*\n",l,r,maxx[cur]);
if(l==r) return;
m=(l+r)/2;
show(l,m,2*cur);
show(m+1,r,2*cur+1);
}

int main()
{
int t,cas,i,res,ans;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
ary[2*i]=-1;
scanf("%d",&ary[2*i+1]);
}
ary[2*n]=-1;
manacher(ary,2*n+1);
for(i=0;i<n-1;i++) book[i]=(book[2*(i+1)]-1)/2;
if(n-2>=0) build(0,n-2,1);

//for(i=0;i<n-1;i++) printf("%d ",book[i]);
//printf("\n");
//show(0,n-2,1);

ans=0;
for(i=0;i<n-1;i++)
{
res=-1;
if(0<=i-book[i]&&i-book[i]<=i-1) query(i-book[i],i-1,i,res,0,n-2,1);
if(res!=-1)
{
//printf("*%d*\n",res);
ans=max(ans,i-res);
}
}

printf("Case #%d: %d\n",cas,3*ans);
}
return 0;
}

/*
100
10
2 2 3 4 4 3 2 2 3 4

10
2 3 4 4 3 2 2 3 4 4

6
1 1 1 1 1 1
*/