Manacher入门
写在前面
manachermanachermanacher比想象中好理解得多
至少它给了我学习字符串的信心
能干啥
manachermanachermanacher,中文马拉车(您别说,这名字还挺形象),主要用于计算字符串每一个位置为对称中心的回文串长度(等价于个数)
包括偶回文,即长度为偶数的回文串
算法流程
考虑下面的问题:给一个字符串,求最长回文子串
我会暴力!
枚举判断O(n3)O(n^3)O(n3)
我会优化!
考虑到以ccc为中心,acbacbacb不是回文串,左右怎么接都不是回文串
所以可以枚举中间点(偶回文判断一下即可),然后向两边拓展
复杂度O(n2)O(n^2)O(n2)
我会玄学!
O(n2)O(n^2)O(n2)还不够 不符合字符串算法均为线性复杂度公理
在此基础上继续优化
我们记录maxrmaxrmaxr为目前找到的回文串右端点的最右的位置 pospospos为这个回文串的对称中心
开一个数组pip_ipi表示回文半径(和其他文章不同,本文回文半径指一个端点到中心的距离,即直接相减)
回文串最本质的特征是什么?左右关于中心对称。
如果一个回文串对称中心的一侧有另一个回文子串,那么对称过去也有一个相同长度的回文子串
黄色部分完全一致,这就是manacher的核心
(先不考虑偶回文)
① i<maxri<maxri<maxr(取不取等于无所谓)
设j,ij,ij,i关于pospospos对称 即j=pos∗2−ij=pos*2-ij=pos∗2−i
根据上面的推导,令pi=pjp_i=p_jpi=pj即可
当然如果jjj为中心的最长回文左端点越界了
那就不能保证上面的性质(实际上可以保证不成立),所以要和j−maxlj-maxlj−maxl(即maxr−imaxr-imaxr−i)取minminmin。
jjj越界时还需要让iii继续拓展。当然为了刷短代码减少讨论,都拓展一下好了
②i≥maxri \geq maxri≥maxr
啥都不能保证,直接暴力扩展
综上:
- 如果i<maxri<maxri<maxr,按上述条件更新pip_ipi
- 暴力拓展
- 更新maxrmaxrmaxr和pospospos
然后……对,没了,就三行。
这就是manachermanachermanacher的全过程,复杂度O(n)O(n)O(n),后面有证明
实现
上面没有讨论偶回文,主要是转化过程比较难看,容易使人丧失信心。
其实也不难。只需要在字符两两之间加一个字符,如‘#’;然后首尾也加上‘#’,再在开头加一个标识符防止越界。注意要和之前的不同,如‘@’
这样偶回文可以看做中心是‘#’的回文
普及T1模拟水平
这样处理后,所有回文串左右端点都是‘#’,然后就可以跑了
证明
什么?不是只改了一个地方吗?怎么变O(n)O(n)O(n)了?
回顾整个流程,真正暴力拓展的时候要么jjj左端点越界,要么iii越界(jjj左端点没越界时,根据反证法,iii实际上无法拓展)
jjj左端点越界时,iii右端点出生点就在maxrmaxrmaxr,再拓展就超出去了
也就是说,每次暴力拓展,都意味着maxrmaxrmaxr更新,而maxrmaxrmaxr只会往右跑
换一个角度,实际上暴力拓展是把maxrmaxrmaxr推到最右边,次数是O(n)O(n)O(n)的
所以总复杂度是O(n)O(n)O(n)的
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#define MAXN 1000005
using namespace std;
char s[MAXN],ss[MAXN];
int pos,maxr;
int p[MAXN];
int main()
{scanf("%s",s+1);int n=strlen(s+1);for (int i=1;i<=n;i++) ss[i<<1]=s[i],ss[(i<<1)|1]='#';n=(n<<1)|1,ss[0]='@',ss[1]='#';strcpy(s,ss);for (int i=1;i<=n;i++){if (i<maxr) p[i]=min(p[(pos<<1)-i],maxr-i);while (s[i-p[i]-1]==s[i+p[i]+1]) ++p[i];if (i+p[i]>maxr) maxr=i+p[i],pos=i;}return 0;
}
由于所有位置为中心的最长回文串左右端点都是‘#’
回文串长度leni=2pi+1−12=pilen_i= \frac {2p_i+1-1}{2} = p_ileni=22pi+1−1=pi
然后用来搞事情就可以了
Manacher入门相关推荐
- 怎么判断一个字符串的最长回文子串是否在头尾_回文自动机入门
缘起 回文自动机(Palindrome auto machine PAM,有些地方称之为回文树)是回文问题的大杀器~ 本文使用一道很简单的题目入门这个精巧的数据结构. hdu 2163 Palind ...
- 创新实践部第一次培训---算法入门
文章目录 引言--我们为什么要学算法 常见基础错误 手(shou)误(jian) 浮点数判等 声明变量和使用变量太远 忘记初始化 数组开小了 变量开小了 建议的代码书写方式 ACM输入输出 ACM错误 ...
- dropwizard 连接mysql_Dropwizard入门及开发步骤
Dropwizard介绍 Dropwizard是一个微服务框架, 是各项技术的一个集成封装.它包含了以下组件: - 嵌入式Jetty,一个应用程序被打包成一个Jar文件,并开始自已嵌入的Jetty容器 ...
- 用Construct 2制作入门小游戏~
今天在软导课上了解到了Construct 2这个神器,本零基础菜鸟决定尝试做一个简单的小游戏(实际上是入门的教程啊= = 首先呢,肯定是到官网下载软件啊,点击我下载~ 等安装完毕后我便按照新手教程开始 ...
- Docker入门六部曲——Swarm
原文链接:http://www.dubby.cn/detail.html?id=8738 准备工作 安装Docker(版本最低1.13). 安装好Docker Compose,上一篇文章介绍过的. 安 ...
- Docker入门六部曲——Stack
原文链接:http://www.dubby.cn/detail.html?id=8739 准备知识 安装Docker(版本最低1.13). 阅读完Docker入门六部曲--Swarm,并且完成其中介绍 ...
- Docker入门六部曲——服务
原文链接:http://www.dubby.cn/detail.html?id=8735 准备 已经安装好Docker 1.13或者以上的版本. 安装好Docker Compose.如果你是用的是Do ...
- 【springboot】入门
简介: springBoot是spring团队为了整合spring全家桶中的系列框架做研究出来的一个轻量级框架.随着spring4.0推出而推出,springBoot可以説是J2SEE的一站式解决方案 ...
- SpringBoot (一) :入门篇 Hello World
什么是SpringBoot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不 ...
最新文章
- 科学处理java.lang.StackOverflowError: null异常
- 安卓dtmf识别_基于Python的DTMF信号识别
- 利用css3实现jQuery中的slideDown和slideUp效果
- OAM Kubernetes 标准实现与核心依赖库发布 | 云原生生态周报 Vol. 52
- Struts2里的Action返回Json数据
- 看漫画,学Linux内核!看完明白小企鹅们在干啥了吧?
- UVA 11825 状态压缩DP+子集思想
- PAT A 1118. Birds in Forest (25)【并查集】
- Java数据解析之XML(原创)
- BZOJ 1688: [Usaco2005 Open]Disease Manangement 疾病管理
- QueryWrapper、LambdaQueryWrapper以及LambdaQueryChainWrapper用法
- 【计算机网络学习笔记04】网络体系架构与网络协议
- 腾讯云:开发者实验室
- dw里PHP编写格式,Dreamweaver中如何使用模板(附代码)
- Android vitamo 实现横竖屏的切换和页面内部的网络视频
- Eclipse java.lang.NoClassDefFoundError: org/dom4j/io/SAXReade 错误解决方法
- springboot学校快递站点管理系统的设计与实现毕业设计源码111544
- Docker:第一章:Docker常用命令
- outlook邮箱链接如何用ie打开_Outlook手机邮箱配置文档
- XDC IO --- Output Delay Constraints(Vivado)
热门文章
- 岛国小姐姐来例假时,男朋友背着她偷偷查手机......
- 为什么大部分男生比女生高?原因让你意想不到
- 数学特级教师:数学除了做题目,我还必须让他们看这些!
- html盒模型向上浮动,HTML5盒模型、浮动和定位
- mvn 打包可执行包_用Maven打包发布可执行的jar包
- java跨库调用存储_存储库仅在第二个调用数据时发送回ViewModel
- http referer 验证防御方法_渗透测试 跨站攻击防御与安全检测手法剖析
- Linux语言写的高通滤波,高通滤波器c语言实现
- 数据结构——图-最短路径长度中最大的一个
- java class类型参数_使用Class对象实例化Java类型参数/ generic