询问区间的最长回文
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200100;
int rad[maxn*2];
char str[maxn],s[maxn*2];
int q;
int odd[maxn],even[maxn];
int mm[maxn],mo[maxn][20],me[maxn][20];
void Manacher(int rad[],char str[],int n){
int i,mx=0,id;
for(i=1;i<n;i++){
if(mx>i) rad[i]=min(rad[2*id-i],mx-i);
else rad[i]=0;
for(;str[i+rad[i]]==str[i-rad[i]];rad[i]++)
;
rad[i]--;
if(mx<rad[i]+i){
mx=rad[i]+i;
id=i;
}
}
}
void init(){
int i;
mm[0]=-1;
for(i=1;i<maxn;i++)
mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
}
void cal_RMQ(int n){
int i,j,k;
for(i=1;i<=n;i++){
mo[i][0]=odd[i];
me[i][0]=even[i];
}
for(i=1;i<=mm[n];i++){
for(j=1;j-1+(1<<i)<=n;j++){
mo[j][i]=max(mo[j][i-1],mo[j+(1<<(i-1))][i-1]);
me[j][i]=max(me[j][i-1],me[j+(1<<(i-1))][i-1]);
}
}
}
int get_RMQ_odd(int x,int y){
int k=mm[y-x+1];
return max(mo[x][k],mo[y-(1<<k)+1][k]);
}
int get_RMQ_even(int x,int y){
int k=mm[y-x+1];
return max(me[x][k],me[y-(1<<k)+1][k]);
}
int main(){
int i,j,n,t,T;
scanf("%d",&T);
init();
for(t=1;t<=T;t++){
scanf("%s",&str[1]);
int len=strlen(&str[1]);
s[0]='$';
for(i=1;i<=len;i++){
s[2*i-1]='#';
s[2*i]=str[i];
}
s[2*len+1]='#';
s[2*len+2]='@';
Manacher(rad,s,2*len+2);
for(i=2;i<=2*len+1;i+=2){
odd[i/2]=rad[i];
even[i/2]=rad[i+1];
}
cal_RMQ(len);
scanf("%d",&q);
for(i=1;i<=q;i++){
int x,y,ans=1;
int h,l,mid;
scanf("%d %d",&x,&y);
l=1,h=(y-x)/2;
while(l<=h){
int mid=(l+h)>>1;
if(get_RMQ_odd(x+mid,y-mid)>=2*mid+1){
l=mid+1;
ans=max(ans,2*mid+1);
}
else
h=mid-1;
}
l=1,h=(y-x+1)/2;
while(l<=h){
int mid=(l+h)>>1;
if(get_RMQ_even(x+mid-1,y-mid)>=2*mid){
l=mid+1;
ans=max(ans,2*mid);
}
else
h=mid-1;
}
printf("%d\n",ans);
}
}
return 0;
}