浅谈Manacher
\(Manacher\)是由一个叫做\(Manacher\)的人发明的能在\(O(n)\)时间内找出一个字符串长度最长的回文子串的算法。
由于偶回文串形如\(abba\)这样的不好找对称中心,所以我们在每个字符串之间插入一个'#',就变成#a#b#b#a#了,这样子就能找到对称中心了。
\(Manacher\)的核心数组\(p_i\):表示以第\(i\)为为对称中心的回文串半径长度为多少(包含\(i\))
| # | a | # | a | # | b | # | a | # | a | # |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 2 | 1 | 6 | 1 | 2 | 3 | 2 | 1 |
上面一行是字符串,下面一行是\(p_i\)数组。
以\(i\)为中心的回文串长度即为\(p_i-1\),这个减一可以看做是把最旁边的那个'#'减掉了,然后半径就跟实际上回文串的长度一样了。
所以\(manacher\)算法的核心就是在\(O(n)\)的时间复杂度内求出\(p\)数组。
令\(mx\)为之前已经求出过的\(p_i+i-1\)的最大值,\(id\)满足\(p_{id}+id-1\)等于\(mx\)的
那么\(p_i= i\leqslant mx?min(mx-i+1,p[id*2-i]):1\)。
这个意思是如果当前位置在\(mx\)左边,那么当前位置的\(p\)肯定是\(mx-i+1\)与我关于\(id\)对称点的\(p\)的最小值。因为那个点与我关于\(id\)对称,所以在\([i,mx]\)这一段内我可以直接继承他的\(p\)数值,但是当前位置已知的回文串长度不能伸到\(mx\)后面去,所以跟\(mx-i+1\)取\(min\)。
然后在暴力判断能不能继续扩张到\(mx\)后面去,最后更新\(id\)和\(mx\)。
时间复杂度分析:
除了暴力扩张\(mx\)以外都是\(O(1)\)的,\(mx\)最多被扩张字符串长度,所以复杂度是\(O(n)\)的。
模板题:https://www.luogu.org/problemnew/show/P3805
时间复杂度:\(O(n)\)
空间复杂度:\(O(n)\)
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=2.2e7+5;
int n,ans;
int p[maxn];
char s[maxn];
int main() {
scanf("%s",s+1);
n=strlen(s+1);
for(int i=n;i;i--)
s[i<<1]=s[i],s[(i<<1)-1]='#';
s[0]='$',s[n<<1|1]='#';n=n<<1|1;
int id=0,mx=0;
for(int i=1;i<=n;i++) {
p[i]=i<=mx?min(mx-i+1,p[id*2-i]):1;
while(s[i-p[i]]==s[i+p[i]])p[i]++;
if(i+p[i]-1>mx)id=i,mx=i+p[i]-1;
ans=max(ans,p[i]);
}
printf("%d\n",ans-1);
return 0;
}
浅谈Manacher的更多相关文章
- 浅谈Manacher算法与扩展KMP之间的联系
首先,在谈到Manacher算法之前,我们先来看一个小问题:给定一个字符串S,求该字符串的最长回文子串的长度.对于该问题的求解.网上解法颇多.时间复杂度也不尽同样,这里列述几种常见的解法. 解法一 ...
- 【字符串算法2】浅谈Manacher算法
[字符串算法1] 字符串Hash(优雅的暴力) [字符串算法2]Manacher算法 [字符串算法3]KMP算法 这里将讲述 字符串算法2:Manacher算法 问题:给出字符串S(限制见后)求出最 ...
- 浅谈Manacher算法
Manacher manacher是一种\(O(n)\)求最长回文子串的算法,俗称马拉车(滑稽) 直接步入正题 首先可以知道的是:每一个回文串都有自己的对称中心,相应的也有自己的最大延伸长度(可以称之 ...
- 浅谈 Fragment 生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...
- 浅谈 LayoutInflater
浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈SQL注入风险 - 一个Login拿下Server
前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...
- 浅谈WebService的版本兼容性设计
在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...
- 浅谈angular2+ionic2
浅谈angular2+ionic2 前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别. 1. 项目所用:angular2+ionic2 ...
随机推荐
- R中的数据重塑函数
1.去除重复数据 函数:duplicated(x, incomparables = FALSE, MARGIN = 1,fromLast = FALSE, ...),返回一个布尔值向量,重复数据的第一 ...
- 20145240《Java程序设计》第三周学习总结
20145240 <Java程序设计>第三周学习总结 教材学习内容总结 个人感觉第三周的学习量还是很大的,需要学习的内容更难了而且量也变多了,所以投入了更多的时间到Java的学习中去. 第 ...
- 对正交频分复用OFDM系统的理解
OFDM系统 正交频分复用OFDM(Orthogonal Frenquency Division Multiplexing)是一种多载波调制技术. 基本思想:在发送端,它将高速串行数据经过串并变换形成 ...
- Linux下解压分包文件zip(zip/z01/z02)
分包压缩的zip文件不能被7z解压,且这种格式是Windows才能创建出来,在Linux下不会以这种方式去压包.下面是在Linux下处理这种文件的做法: 方法一: cat xx.z01 xx.zip ...
- centos 源码安装php5.5
系统环境: CentOS 6.5 / 7.0 x86_64 Fedora 20 x86_64下载 PHP 源码包 # wget http://cn2.php.net/distributions/php ...
- python基础语法学习常见小问题
说明:我是最近觉得python在完成很多工作中方便使用而且功能强大,想突击学习一下.用的是廖雪峰老师的教程,学习python3.X.这里是廖雪峰老师的网站链接: http://www.liaoxuef ...
- 堆栈在linux内存中的使用
链接:https://www.zhihu.com/question/57013926/answer/151506606 1.Linux 内核中使用 task_struct 作为进程描述符,该结构定义在 ...
- java多线程(内附实例:窗口售票问题、人和叉子的问题)
java多线程的开发有两种方法: (1)实现Runnable接口: (2)继承Thread类: 区别: (1)由于java中一个类只能继承一个父类,但是可以实现多个接口,所以实现Runnable接口比 ...
- cplusplus.com
1/ http://www.cplusplus.com/reference/map/multimap/find/ 2. C
- ZC_问题
1. [02][40:15]主键 还需要另外创建 序列? 一直到 [03][31:25]都已经成功的insert了两条数据了,也没见 手动创建 序列... 2. 貌似记得 有地方给 hibernate ...