C++马拉车(Manacher)算法
文章目录
- 功能
- 马拉车算法
- 初始化
- 主体
- 时间复杂度
- 代码
功能
马拉车算法(Manacher’s Algorithm):用O(n)O(n)O(n)的时间得到一个字符串中,以每个字符为中心的最长回文的长度。
马拉车算法
初始化
由于奇数长度的回文串和偶数长度的回文串不太一样,所以我们用玄学操作将一个串里面所有偶数长度回文串变成奇数长度:
例如这个串:S0=abbabaS_0=abbabaS0=abbaba,在其中插入特殊字符使其变成:S=#a#b#b#a#b#a#S=\#a\#b\#b\#a\#b\#a\#S=#a#b#b#a#b#a#。
接下来都对SSS操作,因为SSS中所有的回文串的长度都是奇数(因为,如果有一个偶数长度的回文串,那么它的一端一定是#\##,而另一端是字母,与它是回文串矛盾)。
主体
设dp[i]dp[i]dp[i]表示以iii为中心,最长回文串的半径。下表是SSS的各个dpdpdp值:
iii | 111 | 222 | 333 | 444 | 555 | 666 | 777 | 888 | 999 | 101010 | 111111 | 121212 | 131313 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
S[i]S[i]S[i] | #\## | aaa | #\## | bbb | #\## | bbb | #\## | aaa | #\## | bbb | #\## | aaa | #\## |
dp[i]dp[i]dp[i] | 111 | 222 | 111 | 222 | 555 | 222 | 111 | 222 | 111 | 444 | 111 | 222 | 111 |
只要把dpdpdp算出来了,问题就解决了。
如果用暴力算法,可以在O(n2)O(n^2)O(n2)的时间内算出dpdpdp,但是既然是dpdpdp,就要学会用前面的回文计算现在的回文。
定义如下几个变量(一定要理解):
i
:当前要计算的位置。(i
之前已经计算出来了)right
:当前计算了的,右端点最远的回文串,的右端点。
例如当枚举到i=6
时,right=9
,因为右端点最远的回文串是#a#b#b#a#
。pos
:当前计算了的,右端点最远的回文串,的中心。(pos<i
)
例如当枚举到i=6
时,pos=5
,因为右端点最远的回文串是#a#b#b#a#
。
当i<righti<righti<right时:
看这个图:
(i′i'i′是iii关于pospospos的对称点)
由于红色一段是回文,所以dp[i]dp[i]dp[i]可能等于dp[i′]dp[i']dp[i′]。
为什么说可能,因为还有这种情况:
此时以iii为中心的最长回文串并不等于以i′i'i′为中心的最长回文串,因为加粗的一段一定(因为红色一段是以pospospos为中心的最长回文)不属于以iii为中心的回文。而此时dp[i]=right−idp[i]=right-idp[i]=right−i。
这两种情况取较小值:dp[i]=min{dp[2×pos−i],right−i}dp[i]=\min\{dp[2\times pos-i],right-i\}dp[i]=min{dp[2×pos−i],right−i}
这里得到的dp[i]dp[i]dp[i]是一个最少值,有可能还能变大,还要继续扩张。
当i≥righti\geq righti≥right时:暴力计算。
最后记得更新pospospos和rightrightright。
时间复杂度
暴力更新(代码24行的while
)时,总体上每个点只会被暴力访问一遍,所以是O(n)O(n)O(n)的。
(虽然初始化过后长度扩大了一倍,导致有个常数)
代码
防止暴力更新时越界要在开头另外加一个特殊字符。
感谢Little-Qiao的提醒,要在最后再加一个不一样的字符(@
),否则会被上一组没清空的数据hack掉,但hihocoder的数据有点小弱……
板题:最长回文。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;#define MAXN 110000int dp[MAXN*2+5];//注意数组大小
char str[MAXN*2+5];
int Manacher(char *s){int N=0,len=strlen(s+1);str[0]='$';//防止越界for(int i=1;i<=len;i++){str[++N]='#';str[++N]=s[i];}str[++N]='#',str[++N]='@';//最后再加一个@int right=0,pos=0;for(int i=1;i<=N;i++){if(i<right)dp[i]=min(dp[2*pos-i],right-i);elsedp[right=i]=1;while(str[i-dp[i]]==str[i+dp[i]])dp[i]++;if(i+dp[i]>right)right=i+dp[i],pos=i;}int ret=0;for(int i=1;i<=N;i++)ret=max(ret,dp[i]-1);//找最长回文return ret;
}char S[MAXN+5];int main(){while(~scanf("%s",S+1))printf("%d\n",Manacher(S));
}
C++马拉车(Manacher)算法相关推荐
- [LeetCode][M0005]最长回文子串(Java)(马拉车(Manacher)算法)
题目描述: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab" 注 ...
- 字符串-Manacher算法(你知道马拉车算法吗?)
文章目录 原理 奇偶问题 p[]数组 马拉车求p[] 模板 例题 P3805 [模板]manacher算法 P1659 拉拉队排练 原理 马拉车算法当然不是马拉着车的奇奇怪怪的东西,是Manacher ...
- manacher算法详解(马拉车算法)
马拉车算法 Manacher算法是由题目"求字符串中最长回文子串的长度"而来.比如 abcdcb 的最长回文子串为 bcdcb ,其长度为5. 回文:正着念,反着念都一样 暴力解不 ...
- manacher(马拉车)算法详解
manacher算法,用于求字符串中最长回文串.凡是涉及暴力枚举,一般都会超时,尤其当考虑回文串时,必须前后一起判断,复杂度太高.这时,manacher算法在O(n)时间里解决问题.下面看算法. 回文 ...
- (待填坑)【字符串】manacher(马拉车)算法
知识点 manacher算法可以在时间复杂度为O(n)的情况下,求出一个字符串的最长回文子串的算法. 一 . 实现步骤 ① 在字符串的各个字母中间加上一个字符,使其变成奇数字符串.对于原来是偶数字符串 ...
- 回文字符串—回文子串—Manacher算法
leetcode地址:5. 最长回文子串 解答参考:动态规划.中心扩散.Manacher 算法 问题描述: 给你一个字符串 s,找到 s 中最长的回文子串.比如给定字符串s = "babad ...
- 数据结构与算法之Manacher算法
数据结构与算法之Manacher算法 目录 Manacher算法概述 Manacher算法代码实现 扩展题--如果只能向字符串后面添加字符,怎么让整体串变成回文串,要求填的字符最少 1. Manach ...
- Manacher算法学习笔记 | LeetCode#5
Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...
- [Leetcode][第647题][JAVA][回文子串][动态规划][中心扩展][Manacher 算法]
[问题描述][中等] [解答思路] 1. 暴力 首先明确如何判断一个字符串是否为回文字符串.第一个字符与最后一个字符相同,第二个字符与倒数第二个字符相同-关于中心位置轴对称. 本题要求一共有多少个回文 ...
最新文章
- C#开机启动与退出程序
- oracle timestamp约束,java.lang.ClassCastException:oracle.sql.TIMESTAMP不能转换为java.sql.Timestamp...
- Count Color(poj 2777)
- pyhanlp 共性分析与短语提取
- Android 第二十课 广播机制(大喇叭)----发送自定义广播(包括发送标准广播和发送有序广播)
- .md是什么文件_Element-UI源码阅读之md显示到页面
- 幽幽的灵光射不出你想要的疯狂
- Android 系统(173)---Android中图片的三级缓存
- PHPCMS V9.6.0 SQL注入漏洞EXP
- 【报告分享】2021企业营销数字化转型研究报告.pdf(附下载链接)
- linux常用知识命令
- Django项目实践2 - Django模板(网页多语种支持/国际化)
- HTML5游戏开发5条建议及开发工具分享
- php教程 网易,网易开源镜像使用帮助
- 实验三 Python表达式
- 如何用笔记本组建家庭点歌系统
- tomcat7中get请求中文乱码问题
- 论文笔记——多源融合SLAM的现状与挑战
- 修改数据库长度mysql_mysql 修改数据库长度
- 东师19年春计算机在线作业,东师算法分析与设计20春在线作业1【标准答案】
热门文章
- 一次圆通快递的亲身体验,不满意。
- 卷积神经网络之(使用重复元素的网络)VGG
- 会计学里借贷记账法的借方与贷方(http://hi.baidu.com/honeyxxd/blog/item/7a8c1ed71e5f23dea044df50.html)
- 【svopro】追踪梳理
- 工作的记录,hibernate的evict,load使用
- 春节到,笑一笑,十年少-----笑脸墙大合集(Powered by Smilewall V1.0)
- c# ThreadPool.QueueUserWorkItem线程池的应用
- Exchanger数据交换
- 支付宝2020年度账单出炉!又是白忙活的一年......
- 004--Django(定义模型类、数据的增删改查、F和Q对象)