题目描述

顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同)。

输入长度为 n的串 S ,求 S的最长双回文子串 T ,即可将 T 分为两部分 X, Y,( ∣X∣,∣Y∣≥1|X|,|Y|≥1∣X∣,∣Y∣≥1 )且 X 和 Y 都是回文串。

输入输出格式

输入格式:

一行由小写英文字母组成的字符串 S 。

输出格式:

一行一个整数,表示最长双回文子串的长度。

输入输出样例

输入样例#1:

baacaabbacabb
输出样例#1:

12

说明

【样例说明】

从第二个字符开始的字符串aacaabbacabb可分为aacaabbacabb两部分,且两者都是回文串。

对于100%的数据, 2≤∣S∣≤105

Solution:

  本题$zyys$啊!~

  很容易想到$manacher$,于是先打个板子看看,处理出以$i$为中心的最长回文半径$p[i]$后,就断思路了。

  我首先想到的是,在每次更新$p[i]$后,分别处理出以$i$为中心的半径$p[i]$内,每个位置为开头和结尾的最长回文子串长度($manacher$结束后直接枚举断点就可以得到答案),但是这样强行又将复杂度拉到了$O(n^2)$。于是,开始断线~

  后面看看巨佬们的思路,豁然**,我是真的蠢啊~

  其实,将我开始的思路修改一下即可:

  我们维护最长回文半径$p[i]$的同时,再分别维护两个东西,以$i$为结尾的最长回文子串的长度$ll[i]$,和以$i$为开头的最长回文子串的长度$rr[i]$。

  那么很显然,因为以$i$为中心的最长回文子串长度为$p[i]-1$,所以每次更新$p[i]$后,我们只需处理出当前这个回文子串的左右边界(中间的每个点的$ll[i],rr[i]$可以在$manacher$结束后$O(n)$处理出),则$ll[i+p[i]-1]=max(ll[i+p[i]-1],p[i]-1)$(更新以$i+p[i]-1$为结尾的最长回文长度),同理$rr[i-p[i]+1]=max(rr[i-p[i]+1],p[i]-1)$。

  跑完$manacher$后,我们$O(n)$递推出每个$#$为断点的$ll[i]$和$rr[i]$,其中$rr[i]$因为是$i$结尾的回文长度,所以直接顺推,每往后移一位,最长回文子串长度$-2$,于是$rr[i]=max(rr[i],rr[i-2]-2)$($i-2$是上一个$#$位置),同理$ll[i]$直接逆推,类似地$ll[i]=max(ll[i],ll[i+2]-2)$。

  最后枚举每个$#$为断点,更新$ans$就$OK$了。

代码:

#include<bits/stdc++.h>
#define For(i,a,b,c) for(int (i)=(a);(i)<=(b);(i)+=(c))
#define Bor(i,a,b,c) for(int (i)=(b);(i)>=(a);(i)-=(c))
#define Min(a,b) ((a)>(b)?(b):(a))
#define Max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int N=;
int p[N],ll[N],ans,rr[N],mx,id,cnt;
char s[N],t[N];
int main(){
scanf("%s",t);
int len=strlen(t);
s[++cnt]='$',s[++cnt]='#';
For(i,,len-,)s[++cnt]=t[i],s[++cnt]='#';
s[++cnt]='\0';
For(i,,cnt,){
if(i<mx)p[i]=Min(p[id*-i],mx-i);
else p[i]=;
while(s[i-p[i]]==s[i+p[i]])p[i]++;
if(mx<i+p[i])id=i,mx=i+p[i];
ll[i+p[i]-]=Max(ll[i+p[i]-],p[i]-);
rr[i-p[i]+]=Max(rr[i-p[i]+],p[i]-);
}
For(i,,cnt,)rr[i]=Max(rr[i],rr[i-]-);
Bor(i,,cnt,)ll[i]=Max(ll[i],ll[i+]-);
For(i,,cnt,)if(rr[i]&&ll[i])ans=Max(ans,ll[i]+rr[i]);
cout<<ans;
return ;
}

P4555 最长双回文串的更多相关文章

  1. P4555 [国家集训队]最长双回文串

    P4555 [国家集训队]最长双回文串 manacher 用manacher在处理时顺便把以某点开头/结尾的最长回文串的长度也处理掉. 然后枚举. #include<iostream> # ...

  2. 洛谷 P4555 [国家集训队]最长双回文串 解题报告

    P4555 [国家集训队]最长双回文串 题目描述 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同). 输入长度为\(n\)的串 ...

  3. Manacher || P4555 [国家集训队]最长双回文串 || BZOJ 2565: 最长双回文串

    题面:P4555 [国家集训队]最长双回文串 题解:就.就考察马拉车的理解 在原始马拉车的基础上多维护个P[i].Q[i]数组,分别表示以i结尾最长回文子串的长度和以i开头的最长回文子串的长度 然后就 ...

  4. 【洛谷】P4555 [国家集训队]最长双回文串

    P4555 [国家集训队]最长双回文串 题源:https://www.luogu.com.cn/problem/P4555 原理:Manacher 还真比KMP好理解 解决最长回文串问题 转化为长度为 ...

  5. BZOJ 2565: 最长双回文串 [Manacher]

    2565: 最长双回文串 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1842  Solved: 935[Submit][Status][Discu ...

  6. 【BZOJ2565】最长双回文串(回文树)

    [BZOJ2565]最长双回文串(回文树) 题面 BZOJ 题解 枚举断点\(i\) 显然的,我们要求的就是以\(i\)结尾的最长回文后缀的长度 再加上以\(i+1\)开头的最长回文前缀的长度 至于最 ...

  7. BZOJ.2565.[国家集训队]最长双回文串(Manacher/回文树)

    BZOJ 洛谷 求给定串的最长双回文串. \(n\leq10^5\). Manacher: 记\(R_i\)表示以\(i\)位置为结尾的最长回文串长度,\(L_i\)表示以\(i\)开头的最长回文串长 ...

  8. Tsinsen 最长双回文串

    求最长双回文串,正反建回文树求最大. 题目链接:http://www.tsinsen.com/ViewGProblem.page?gpid=A1280 By:大奕哥 #include<bits/ ...

  9. bzoj 2565: 最长双回文串 manacher算法

    2565: 最长双回文串 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem. ...

随机推荐

  1. Android(java)学习笔记91:Eclipse中代码提示去掉@override,不然就报错!

    1. Eclipse中提示去掉@Override 把项目下载下来后有@Override的注释的方法会报错,如果把@Override去掉就不报错了.经过查阅后发现:@override注释在jdk1.5环 ...

  2. 【BZOJ2733】[HNOI2012] 永无乡(启发式合并Splay)

    点此看题面 大致题意: 给你一张图,其中每个点有一个权值,有两种操作:在两点之间连一条边,询问一个点所在联通块第\(k\)小的权值. 平衡树 看到第\(k\)小,应该不难想到平衡树. 为了练习\(Sp ...

  3. 浅谈 import / export

    import { ngModule } from '@angular/core'; import { AppComponent } from './app.component'; export cla ...

  4. pytho线程信号量

    pytho线程信号量 import threading,time def going(num,sleep_time): semaphore.acquire()#启动允许执行 print("g ...

  5. javaweb基础(32)_jdbc学习入门

    一.JDBC相关概念介绍 1.1.数据库驱动 这里的驱动的概念和平时听到的那种驱动的概念是一样的,比如平时购买的声卡,网卡直接插到计算机上面是不能用的,必须要安装相应的驱动程序之后才能够使用声卡和网卡 ...

  6. S运算符&&和|| 及其优先级

    a && b : 将a, b转换为Boolean类型, 再执行逻辑与, true返回b, false返回aa || b : 将a, b转换为Boolean类型, 再执行逻辑或, tru ...

  7. d3.js--01

    D3 的全称是(Data-Driven Documents),顾名思义可以知道是一个被数据驱动的文档.听名字有点抽象,说简单一点,其实就是一个 JavaScript 的函数库,使用它主要是用来做数据可 ...

  8. 转载:jsonp详解

    json相信大家都用的多,jsonp我就一直没有机会用到,但也经常看到,只知道是“用来跨域的”,一直不知道具体是个什么东西.今天总算搞明白了.下面一步步来搞清楚jsonp是个什么玩意. 同源策略 首先 ...

  9. python字典按照k,v来排序

    按照 k 排序 按照 v 排序

  10. 关于Linux系统下zookeeper集群的搭建

    1.集群概述 1.1什么是集群 1.1.1集群概念 集群是一种计算机系统, 它通过一组松散集成的计算机软件和/或硬件连接起来高度紧密地协作完成计算工作.在某种意义上,他们可以被看作是一台计算机.集群系 ...