原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2565
最长双回文串
Description
顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
Input
一行由小写英文字母组成的字符串S。
Output
一行一个整数,表示最长双回文子串的长度。
Sample Input
baacaabbacabb
Sample Output
12
HINT
样例说明
从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。
对于100%的数据,2≤|S|≤10^5
2015.4.25新加数据一组
题解
这提题分三步:
用哈希求出以每个串结尾的回文串多长;
枚举分界点尝试拼在一起;
AC A C ;
代码
#include<bits/stdc++.h>
#define ls v<<1
#define rs v<<1|1
using namespace std;
const int M=2e6+5;
struct sd{
int lm,mx,rm,sum;
sd(){lm=mx=rm=sum=-1e9;}
};
sd get(int a,int b,int c,int d){sd x;x.lm=a,x.mx=b,x.rm=c,x.sum=d;return x;}
int lm[M],rm[M],mx[M],sum[M],que[M],n,m;
void in(){scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)scanf("%d",&que[i]);}
void up(int v){sum[v]=sum[ls]+sum[rs],lm[v]=max(lm[ls],sum[ls]+lm[rs]),rm[v]=max(rm[rs],rm[ls]+sum[rs]),mx[v]=max(max(mx[ls],mx[rs]),rm[ls]+lm[rs]);}
void build(int v,int le,int ri)
{
if(le==ri){sum[v]=lm[v]=rm[v]=mx[v]=que[le];return;}
int mid=le+ri>>1;build(ls,le,mid);build(rs,mid+1,ri);up(v);
}
sd ask(int v,int le,int ri,int lb,int rb)
{
if(lb<=le&&ri<=rb){return get(lm[v],mx[v],rm[v],sum[v]);}
int mid=le+ri>>1;sd ll,rr,ans;
if(lb<=mid)ll=ask(ls,le,mid,lb,rb);if(mid<rb)rr=ask(rs,mid+1,ri,lb,rb);
ans.lm=max(ll.lm,ll.sum+rr.lm),ans.rm=max(rr.rm,ll.rm+rr.sum),ans.mx=max(max(ll.mx,rr.mx),ll.rm+rr.lm);
return ans;
}
void modify(int v,int le,int ri,int pos,int val)
{
if(le==ri){mx[v]=lm[v]=rm[v]=sum[v]=val;return;}
int mid=le+ri>>1;if(pos<=mid)modify(ls,le,mid,pos,val);if(mid<pos)modify(rs,mid+1,ri,pos,val);up(v);
}
void ac()
{
int op,x,y;build(1,1,n);
while(m--)
{
scanf("%d%d%d",&op,&x,&y);
if(op==1){if(x>y)swap(x,y);printf("%d\n",ask(1,1,n,x,y).mx);}
else modify(1,1,n,x,y);
}
}
int main(){in();ac();}