给定字符串求其最长双回文子串,双回文子串的定义是该串可以分成两个串它们都是回文串。
详见GDKOI2016的项链
我直接超标了(不知所措
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=100000+10;
int f[maxn*4];
int tree[maxn*20];
int i,j,k,l,r,t,n,m,ans,tot;
char ch;
char s[maxn*2],h[maxn*4];
void change(int p,int l,int r,int a,int b){
if (l==r){
tree[p]=b;
return;
}
int mid=(l+r)/2;
if (a<=mid) change(p*2,l,mid,a,b);else change(p*2+1,mid+1,r,a,b);
tree[p]=max(tree[p*2],tree[p*2+1]);
}
int query(int p,int l,int r,int a,int b){
if (a>b) return 0;
if (l==a&&r==b) return tree[p];
int mid=(l+r)/2;
if (b<=mid) return query(p*2,l,mid,a,b);
else if (a>mid) return query(p*2+1,mid+1,r,a,b);
else return max(query(p*2,l,mid,a,mid),query(p*2+1,mid+1,r,mid+1,b));
}
int main(){
while (1){
ch=getchar();
if (ch<'a'||ch>'z') break;
s[++n]=ch;
}
h[0]='@';
h[1]='$';
fo(i,1,n) h[i*2]=s[i],h[i*2+1]='$';
h[n*2+2]='%';
j=0;
f[0]=0;
fo(i,2,n*2){
if (i>j+f[j]){
f[i]=0;
while (h[i+f[i]+1]==h[i-f[i]-1]) f[i]++;
}
else{
f[i]=min(f[2*j-i],j+f[j]-i);
while (h[i+f[i]+1]==h[i-f[i]-1]) f[i]++;
}
if (i+f[i]>j+f[j]) j=i;
}
fo(i,3,n+2) change(1,1,n*2+1,i-f[i],i);
fo(i,2,n*2){
ans=max(ans,query(1,1,n*2+1,1,i+f[i])-i);
if (i+n+1<=n*2) change(1,1,n*2+1,i+n+1-f[i+n+1],i+n+1);
}
printf("%d\n",ans);
}