BZOJ2565 最长双回文串

原题链接: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();}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值