[国家集训队]最长双回文串 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 ,即可 ...
随机推荐
- MySQL高级-全局查询日志
注意:全局查询日志不要在生成环境中启用 一.配置启用 二.编码启用
- 「日常训练」Balancing Act(POJ-1655)
题意与分析 树的重心板子题. 值得考虑的是,重心究竟有哪些优秀的性质? 这里是一些网上能看到的性质: (判定性质)找到一个点,其所有的子树中最大的子树节点数最少(子树可以"倒着看" ...
- selenium,unittest——参数化url,并多线程加快脚本运行速度
利用参数化连续打开网页: #encoding=utf-8import unittestimport paramunittestimport timefrom selenium import webdr ...
- 375. Clone Binary Tree【LintCode java】
Description For the given binary tree, return a deep copy of it. Example Given a binary tree: 1 / \ ...
- Java中定时器相关实现的介绍与对比之:Timer和TimerTask
Timer和TimerTask JDK自带,具体的定时任务由TimerTask指定,定时任务的执行调度由Timer设定.Timer和TimerTask均在包java.util里实现. 本文基于java ...
- mahout协同过滤算法各接口
Mahout协同过滤算法 Mahout使用了Taste来提高协同过滤算法的实现,它是一个基于Java实现的可扩展的,高效的推荐引擎.Taste既实现了最基本的基于用户的和基于内容的推荐算法,同时也提供 ...
- CentOS Openvpn搭建以及 linux&&windows客户端的连接
本文参考:http://www.centoscn.com/CentosServer/test/2014/1120/4153.html 一. Server安装准备 (CentOS release ...
- Python的top-level脚本为什么在磁盘上没有对应的字节码?
在Python中,如果你使用python script.py这样的方式运行Python脚本,那么script.py就被称为top-level脚本.对于Python来说,这个脚本的字节码是不会写入到磁盘 ...
- 使用libpcab抓包&处理包
#include <stdio.h> #include <stdlib.h> #include <strings.h> #include <string.h& ...
- sql查询 同一个字段下另一个字段个数
select seriesid , count(reportid) from reportsystem group by seriesidhaving count(reportid) > 1