【洛谷 P3805】 【模板】manacher算法
题目链接
manacher算法:在线性时间内求一个字符串中所有/最长回文串的算法。
先来考虑一下暴力的算法,枚举每个中点,向两边扩展,时间复杂度\(O(n^2)\)。
来分析下此算法的缺点。
1、因为回文串有奇偶之分,所以要分类讨论,\(abba\)的对称轴不在字符上,分类讨论就会有点麻烦。
为此,\(manacher\)算法的解决方案是在每个字符之间插入一个相同的字符,比如说\(\#\),
\(ababa->\#a\#b\#a\#b\#a\#\),这样就不用考虑回文串的奇偶性了。
2、效率低。为什么低?每个位置会被重复遍历。和\(KMP\)算法类似,\(manacher\)也是利用已有信息减少重复无用操作。
比如说\(abacaba\),这是一个回文串,但两边的\(aba\)也都是一个回文串,我们在枚举到右边的\(b\)时就已经能确定已这个\(b\)为中心的回文串的回文半径至少为\(2\),然后直接从这个长度开始拓展就好了。设\(hw[i]\)表示以\(a[i]\)为回文中心的回文半径长度,\(maxright\)表示当前已发现的右端点最右的右端点,\(mid\)表示这个回文串的中心。
则有如下算法(我觉得看代码比看讲解容易懂些)
for(int i = 1; i < len; ++i){
if(i < maxright)
hw[i] = min(hw[(mid << 1) - i], hw[mid] + mid - i); //min左边的参数是这个点的对称点的hw值,右边的是保证这个部分在这个大回文串之内
else hw[i] = 1;
while(a[i + hw[i]] == a[i - hw[i]]) ++hw[i]; //拓展
if(hw[i] + i > maxright){ //更新右端点
maxright = hw[i] + i;
mid = i;
}
}
该题完整代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 11000010;
char b[MAXN], a[MAXN << 1];
int hw[MAXN << 1], ans, n;
int main(){
scanf("%s", b);
a[0] = a[1] = '#';
int len = strlen(b);
for(int i = 0; i < len; ++i)
a[(i << 1) + 2] = b[i], a[(i << 1) + 3] = '#';
int maxright = 0, mid; len = (len << 1) + 3;
for(int i = 1; i < len; ++i){
if(i < maxright)
hw[i] = min(hw[(mid << 1) - i], hw[mid] + mid - i);
else hw[i] = 1;
while(a[i + hw[i]] == a[i - hw[i]]) ++hw[i];
if(hw[i] + i > maxright){
maxright = hw[i] + i;
mid = i;
}
ans = max(ans, hw[i] - 1);
}
printf("%d\n", ans);
return 0;
}
【洛谷 P3805】 【模板】manacher算法的更多相关文章
- 洛谷P3805 [模板]Manacher算法 [manacher]
题目传送门 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入输出格式 输入格式: 一行小写英文字符a,b,c...y,z组成的字符 ...
- 洛谷.3805.[模板]manacher算法
题目链接 之前做很早了没写这篇,补上. 记录当前ex[]最大的回文中心id和最远延伸范围mx! 关于串的构造: 应该是 @ #A#B#C#B#A# $ ,而不是 @ A#B#C#B#A $ 比如 @a ...
- 洛谷 P3805 【模板】manacher算法
洛谷 P3805 [模板]manacher算法 洛谷传送门 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入格式 一行小写英文字符 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 洛谷 P3805【模板】manacher算法
题目链接:https://www.luogu.com.cn/problem/P3805 Manacher算法$O(n)$: 求以每个字符为中心的最长回文串的半径:如果要求可以以字符间隙为回文中心,就要 ...
- [洛谷P3805]【模板】manacher算法
题目大意:给你一个字符串,求出它的最长回文字段 题解:$manacher$算法 卡点:$p$数组未开两倍空间 C++ Code: #include <cstdio> #include &l ...
- 洛谷P3375 [模板]KMP字符串匹配
To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- 【AC自动机】洛谷三道模板题
[题目链接] https://www.luogu.org/problem/P3808 [题意] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. [题解] 不再介绍基础知识了,就是裸的模 ...
随机推荐
- Messy Code in Windows Server 2008 R2 English Edition
We always use Windows Server 2008 R2 English operation system. And it doesn't have any problem ...
- AD-Powershell for Active Directory Administrators
Table of Contents Computer object commands Group object commands Organizational Unit (OU) commands ...
- 【APUE】Chapter16 Network IPC: Sockets & makefile写法学习
16.1 Introduction Chapter15讲的是同一个machine之间不同进程的通信,这一章内容是不同machine之间通过network通信,切入点是socket. 16.2 Sock ...
- Linux-Shell脚本编程-学习-6-Shell编程-使用结构化命令-文件比较-case编程
这一片主要说test文件的比较,文件比较在日常使用的频率比较高,这里重点把每个部分都试着说说看 1. 检车目录 -d -d测试会检查指定的文件名是否在系统上以目录的形式存在,当我们要写文件到某个目录之 ...
- 剑指offer-二叉树的镜像18
题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ ...
- Windows server 2012 R2开机进入cmd,关闭后黑屏问题
原因分析: 因为自己在卸载IIS的时候,不小心卸载了.net framework,系统没有了图形界面(由完整模式Full变为了核心模式core),需要重新恢复.net framework4.5. 解决 ...
- pta结构体链表作业
一.PTA实验作业 7-2 1. 本题PTA提交列表 2. 设计思路 题目要求按照年龄从大到小的顺序依次输出,于是我只要用冒泡法把结构体变量从大到小排列就可以了. 3.本题调试过程碰到问题及PTA提交 ...
- C语言单元测试
转自http://blog.csdn.net/colin719/article/details/1420583 对于敏捷开发来说,单元测试必不可少,对于Java开发来说,JUnit非常好,对于C++开 ...
- 【EasyNetQ】- 控制队列名称
在为队列生成名称时,EasyNetQ的默认行为是使用消息类型名称并将其附加到订阅ID.例如PartyInvitation,命名空间中的消息类型EasyNetQ.Tests.Integration将使用 ...
- RabbitMQ 的行为艺术
RabbitMQ 的行为艺术 目录 简介 环境搭建 示例一:简单的 Hello World 示例二:发布/订阅模式 尝试发现 - 新物种 EasyNetQ 简介 RabbitMQ:一个消息系统,基于 ...