[国家集训队]最长双回文串 manacher
题解:
首先有一个直观的想法,如果我们可以求出对于位置i的最长后缀回文串和最长前缀回文串,那么我们枚举分界点然后合并前缀和后缀不就可以得到答案了么?
所以我们的目标就是求出这两个数列,
我们令f[i] 表示以i为结尾的最长回文后缀的长度,g[i]表示以i为开头的最长回文后缀的长度。
由于要找回文串,因此我们先想到manacher。
然后我们可以发现对于这样一个串:
原串:xxxxxxxxxx
新串:#x#x#x#x#x#x#x#x#x#x#
我们可以观察到,假设这时我们已经求出了f和g,那么对于任意位置而言,合并出的最长双回文串中,都是“偶串”,且有一半是'#',一半是原串。
因此我们可以直接合并f[i-1] 和 g[i],并用ans记录最大值,那么这时真正的答案就是ans / 2.

假设我们manacher已经求到了第i位,此时i的最长回文半径是R,且j已经被包括在R里面了,那么显然i对j的贡献是(j - i) * 2 + 1。
而因为贡献只和i与j的位置有关,并且我们的i是从1开始,逐渐递增的,因此对于任意一个j,第一次将它更新的i必然可以产生最优解,因此每个j会且仅会被更新一次。
而被更新的j显然也是递增的,因为如果j后面的k已经被更新的话,说明之前已经有一个i可以使得k被覆盖在内了。那么j既然在k前面,肯定也被覆盖过了,
因此求出f[j]时,j肯定是递增的(也就是说肯定是先求出前面的在求出后面的),因此我们可以直接维护一个指针t(这个指针只是字面上的指针),表示当前已经更新到了t,
一旦被覆盖的MaxRight > t,我们就直接用当前的i来更新t。
对于前缀回文串,我们直接把字符串翻转过来,然后再做一遍相同的操作,再把得到的数组反转回来就可以了
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 202000
/*处理出前缀半径和后缀半径,然后合并。可以发现,在扩充了数列之后(#),
获取的最长双回文串一定是偶串,且# 和 真实字符数量相同。
因此ans就是合并后的最长长度/2*/
int n, pos, maxn, ans;
int f[AC], g[AC], tmp[AC], r[AC];
char s[AC], p[AC]; void pre()//读入
{
scanf("%s", s + );
n = strlen(s + );
for(R i = n; i; --i) s[i * ] = s[i];
n = * n + ;
for(R i = ; i <= n; i += ) s[i] = '#';
for(R i = ; i <= n; i++) p[i] = s[n - i + ];//把原串倒过来做一遍就是后缀了
s[] = p[] = '$', s[n + ] = p[n + ] = '$';
} void build()//处理出前缀半径和后缀半径
{
int t = ;
pos = maxn = ;
for(R i = ; i <= n; i++)
{
r[i] = maxn > i ? min(r[ * pos - i], maxn - i + ) : ;
while(s[i - r[i]] == s[i + r[i]]) ++r[i];
if(i + r[i] - > maxn)
{
maxn = i + r[i] - , pos = i;
if(maxn > t)//更新后缀
{
for(R j = t + ; j <= maxn; j++) f[j] = (j - i) * + ;
t = maxn;
}
}
}
pos = maxn = t = ;
for(R i = ; i <= n; i++)
{
r[i] = maxn > i ? min(r[ * pos - i], maxn - i + ) : ;
while(p[i - r[i]] == p[i + r[i]]) ++r[i];
if(i + r[i] - > maxn)
{
maxn = i + r[i] - , pos = i;
if(maxn > t)//更新后缀
{
for(R j = t + ; j <= maxn; j++) tmp[j] = (j - i) * + ;
t = maxn;
}
}
}
for(R i = ; i <= n; i++) g[i] = tmp[n - i + ];
// for(R i = 1; i <= n; i++) printf("%d ", f[i]);
// printf("\n");
} inline void upmax(int &a, int b)
{
if(b > a) a = b;
} void work()//合并
{
for(R i = ; i <= n; i++)
upmax(ans, f[i - ] + g[i]);
printf("%d\n", ans/);
} int main()
{
freopen("in.in", "r", stdin);
pre();
build();
work();
fclose(stdin);
return ;
}
[国家集训队]最长双回文串 manacher的更多相关文章
- BZOJ.2565.[国家集训队]最长双回文串(Manacher/回文树)
BZOJ 洛谷 求给定串的最长双回文串. \(n\leq10^5\). Manacher: 记\(R_i\)表示以\(i\)位置为结尾的最长回文串长度,\(L_i\)表示以\(i\)开头的最长回文串长 ...
- luoguP4555 [国家集训队]最长双回文串 manacher算法
不算很难的一道题吧.... 很容易想到枚举断点,之后需要处理出以$i$为开头的最长回文串的长度和以$i$为结尾的最长回文串的长度 分别记为$L[i]$和$R[i]$ 由于求$R[i]$相当于把$L[i ...
- 洛谷P4555 [国家集训队]最长双回文串(manacher 线段树)
题意 题目链接 Sol 我的做法比较naive..首先manacher预处理出以每个位置为中心的回文串的长度.然后枚举一个中间位置,现在要考虑的就是能覆盖到i - 1的回文串中 中心最靠左的,和能覆盖 ...
- P4555 [国家集训队]最长双回文串
P4555 [国家集训队]最长双回文串 manacher 用manacher在处理时顺便把以某点开头/结尾的最长回文串的长度也处理掉. 然后枚举. #include<iostream> # ...
- 洛谷 P4555 [国家集训队]最长双回文串 解题报告
P4555 [国家集训队]最长双回文串 题目描述 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同). 输入长度为\(n\)的串 ...
- Manacher || P4555 [国家集训队]最长双回文串 || BZOJ 2565: 最长双回文串
题面:P4555 [国家集训队]最长双回文串 题解:就.就考察马拉车的理解 在原始马拉车的基础上多维护个P[i].Q[i]数组,分别表示以i结尾最长回文子串的长度和以i开头的最长回文子串的长度 然后就 ...
- 【洛谷】P4555 [国家集训队]最长双回文串
P4555 [国家集训队]最长双回文串 题源:https://www.luogu.com.cn/problem/P4555 原理:Manacher 还真比KMP好理解 解决最长回文串问题 转化为长度为 ...
- Manacher【p4555】 [国家集训队]最长双回文串
题目描述 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同). 输入长度为 n 的串 S ,求 S 的最长双回文子串 T ,即可 ...
- P4555 [国家集训队]最长双回文串(回文树)
题目描述 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同). 输入长度为 n 的串 S ,求 S 的最长双回文子串 T ,即可 ...
随机推荐
- 一种精准monkey测试的方法
WeTest 导读 相信大家都知道移动端应用的monkey测试吧,不知你们有没有为monkey测试的太过于随机性的特性有过困扰,至少在我们这种界面控件较少且控件位置较偏的app的使用上其测试有效性大打 ...
- Java多线程之volatile与synchronized比较
可见性: JAVA内存模型: java为了加快程序的运行效率,对一些变量的操作是在寄存器或者CPU缓存上进行的,后面再同步到主存中 看上图,线程在运行的过程中,会从主内存里面去去变量,读到自己的空间内 ...
- 180706-BigDecimal除法的精度问题
BigDecimal除法的精度问题 在使用BigDecimal的除法时,遇到一个鬼畜的问题,本以为的精度计算,结果使用返回0,当然最终发现还是自己的使用姿势不对导致的,因此记录一下,避免后面重蹈覆辙 ...
- 对网页进行截图(selenium)
import os def insert_img(driver,file_name): #获取当前路径,并转换为字符串 base_dir=str(os.path.dirname(__file__)) ...
- Java开发工程师(Web方向) - 04.Spring框架 - 第3章.AOP技术
第3章--AOP技术 Spring框架 - AOP概述 笔记https://my.oschina.net/hava/blog/758873Spring框架 - AOP使用 笔记https://my.o ...
- Angular6项目搭建
参照 草根专栏- ASP.NET Core + Ng6 实战:https://v.qq.com/x/page/b076702elvw.html 安装工具: Nodejs, npm 最新版, h ...
- zookeeper:一.zookeeper集群安装
1.zookeeper简介2.安装zookeeper2.1 安装环境准备2.2 安装zookeeper2.2.1.解压zookeeper压缩包到/opt/zookeeper2.2.2.编辑zookee ...
- es6从零学习(二):promise
es6从零学习(二):promise 一:promise的由来 某些情况下,回调嵌套很多时,代码就会非常繁琐,会给我们的编程带来很多的麻烦,这种情况俗称——回调地狱.由此,Promise的概念就由社区 ...
- Pipeline组测试说明
PIPELINE组测试报告 前言:我们组与学霸系统的其他两个小组共同合作开发,组成学霸系统的团体工作.作为学霸系统的一环,我们组起到承上启下的作用,因此,面向群体以及功能实现都是为给下一个组的工作做好 ...
- ACM 第十六天
计算几何 练习题: F - Beauty Contest POJ - 2187 Bessie, Farmer John's prize cow, has just won first place in ...