Manacher(马拉车)
Able was I ere I saw Elba. ----Napoléon Bonaparte(拿破仑)
一、回文串&回文子串
这个很好理解。
如果一个字符串正着读和反着读是一样的,那它就是回文串。 eg. abba ;
如果一个字符串 S 的子串 SS 为回文串,那么 SS 即为 S 的回文子串;若 SSS 为 S 的回文子串中最长的一个,那么我们称 SSS 为 S 的最长回文子串。
二、Manacher算法
如何找到一个字符串的最长回文子串呢?
我们很容易想到一个 O(n2) 的方法,即:从每个字符开始向两边爆搜。但显然,这个方法效率太低下了。
如何快速求出答案,这就是 Manacher算法的事了。
Ⅰ. 奇回文&偶回文
字面意思,不再赘述。
如果同时存在奇回文和偶回文,那么处理起来会比较的繁琐,下面就是Manacher 一个很巧妙的方法了:在字符串收尾,即各字符间插入一个特殊的字符(指没有出现过的字符),例如:
aba ----> #a#b#a#
abba ----> #a#b#b#a#
这样,所有的回文串就都成奇回文了。

inline int Pre()
{
S[0]='@',S[1]='#';
int j(1);
for(register int i=0,len=IP.size();i<len;++i) S[++j]=IP[i],S[++j]='#';
S[++j]='\0';return j;
}
预处理
Ⅱ. 最长回文半径
令一个回文串中最左或最右位置的字符与其对称轴的距离称为 " 回文半径 ",令 R [ i ] 表示字符 i 的最长回文半径。
| i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| S | @ | a | # | b | # | b | # | a | # | b | $ |
| R[i] | 边界 | 1 | 1 | 2 | 4 | 2 | 1 | 4 | 1 | 2 | 边界 |
显然,R [ i ] - 1 即为以 i 为中心的最长回文子串的长度。
那么,我们要求的最长回文子串,就成了 max { R [ i ] - 1 } 。
如何快速求出 R [ ] ???
Ⅲ. Manacher
从左往右依次讨论。
设 Max 为已讨论的子串中能达到的右端最大位置,P 为提供当前 Max 的字符位置。如下表:
| i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| Max的对称点 | P | Max |
接下来讨论的位置 i 可以分为两种情况:小于等于 Max ,大于 Max:
1. 小于等于 Max :
| i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| Max的对称点 | j(i的对称点) | P | i | Max |
由于 i 和 j 对称 ,所以求出 i 的对称点 j ,简直是 "轻易而举" 。
不难发现现在有可以分为两种情况讨论:
( 1 ) . 以 j 为对称轴的回文串比较短:那么可以直接令 R [ i ] = R [ j ] ;
( 2 ) . 以 j 为对称轴的回文串比较长:此时,我们只能确定不超过 Max 的部分的情况,对于 Max 以外的,我们需要以 i 为中心开始往两侧拓展,直到两侧不同,同时更新 p 和 Max。
2. 大于 Max : 这种情况很好处理,直接拓展就可以了(当然,要同时更新 p 和 Max)
Ⅳ. 代码

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
char S[50000005];
int m,R[50000005];
string IP;
inline int Pre()
{
S[0]='@',S[1]='#';
int j(1);
for(register int i=0,len=IP.size();i<len;++i) S[++j]=IP[i],S[++j]='#';
S[++j]='\0';return j;
}
inline int Manacher()
{
m=Pre();
int RET(-1),x(0),Max(0);
for(register int i=1;i<m;++i)
{
if(i<Max) R[i]=min(R[2*x-i],Max-i+1);
else R[i]=1;
while(S[i-R[i]]==S[i+R[i]]) ++R[i];
if(Max<i+R[i]-1) x=i,Max=i+R[i]-1;
RET=max(RET,R[i]-1);
}
return RET;
}
int main()
{
ios::sync_with_stdio(false);
cin>>IP,cout<<Manacher();
return 0;
}
Manacher
Ⅴ. 时间复杂度
由于Max是不断向右拓展的,最多拓展 n 次,不难得出 马拉车 的时间复杂度是线性的,即 O( n )。
Manacher(马拉车)的更多相关文章
- Manacher(马拉车)算法(jekyll迁移)
layout: post title: Manacher(马拉车)算法 date: 2019-09-07 author: xiepl1997 cover: 'assets/img/manacher.p ...
- manacher(马拉车算法)
Manacher(马拉车算法) 序言 mannacher 是一种在 O(n)时间内求出最长回文串的算法 我们用暴力求解最长回文串长度的时间复杂度为O(n3) 很明显,这个时间复杂度我们接受不了,这时候 ...
- HDU - 3068 最长回文manacher马拉车算法
# a # b # b # a # 当我们遇到回判断最长回文字符串问题的时候,若果用暴力的方法来做,就是在字符串中间添加 #,然后遍历每一个字符,找到最长的回文字符串.那么马拉车算法就是在这个基础上进 ...
- Manacher (马拉车) 算法:解决最长回文子串的利器
最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...
- Manacher马拉车
俗话说:摩托再好,不如骡拉啊(好像不是骡) Manacher就是O(N)计算最长回文子串的算法. 其中我们需要在0位置加入字符“$",然后原字符串中每两个字符加入一个"#" ...
- manacher马拉车算法
Manacher算法讲解 总有人喜欢搞事情,出字符串的题,直接卡掉了我的40分 I.适用范围 manacher算法解决的是字符串最长回文子串长度的问题. 关键词:最长 回文 子串 II.算法 1.纯暴 ...
- 最长回文子串 —— Manacher (马拉车) 算法
最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...
- manacher/马拉车常用用法一览
因为manacher算法把原来的字符串扩大了两倍,因此在应用时许多二级结论都非常不直观,现场推出来很麻烦,因此笔者在此做个简单整理,如果发现有错误或者有常用的我没有涉及到的,恳请在下方评论区指出,我会 ...
- Manacher(马拉车)算法
Manacher算法是一个求字符串的最长回文子串一种非常高效的方法,其时间复杂度为O(n).下面分析以下其实行原理及代码: 1.首先对字符串进行预处理 因为回文分为奇回文和偶回文,分类处理比较麻烦,所 ...
随机推荐
- 通过mstsc复制粘贴失败需要重新启动RDP剪切板监视程序rdpclip.exe
先结束程序 再重新启动程序
- 谈谈raft fig8 —— 迷惑的提交条件和选举条件
谈谈raft fig8 -- 迷惑的提交条件和选举条件 前言 这篇文章的思路其实在两个月前就已经成型了,但由于实习太累了,一直没来得及写出来.大概一个月前在群里和群友争论fig8的一些问题时,发现很多 ...
- RMQ区间最值查询
RMQ区间最值查询 概述 RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A, 回答若干询问RMQ(A,i,j)(i,j<= ...
- php保留2位小数方法
$num = 10.4567; //第一种:利用round()对浮点数进行四舍五入 echo round($num,2); //10.46 //第二种:利用sprintf格式化字符串 $format_ ...
- xmind使用技巧
xmind看似每个人都会使用,但是掌握一些小技巧,能够有效提升工作效率. 多行复制粘贴 在xmind中选中多行,复制然后可以直接粘贴到excel.word当中. 在excel.word选中多行,复制然 ...
- [转载]Nginx负载均衡配置实例详解
负载均衡是我们大流量网站要做的一个东西,下面我来给大家介绍在Nginx服务器上进行负载均衡配置方法,希望对有需要的同学有所帮助哦. 负载均衡 先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可 ...
- python接口自动化--json解析神器jsonpath
前言 做接口测试的时候,大部分情况下返回的是json数据,我们需要对返回的json断言. 当返回的数据量比较大,并且嵌套的层级很深的时候,很多小伙伴不会取值,往往在返回结果取值上浪费很多时间.一直在寻 ...
- JQuery EasyUI 结合ztrIee的后台页面开发
JQuery EasyUI 结合 zTree树形结构制作web页面.easyui用起来比较简单,很好的封装了jquery的部分功能,使用起来更加方便,但是从1.2.3版本以后,商业用途是需要付费的, ...
- 10.6 Nginx 高并发连接
Nginx 高并发连接 什么是IO,输入输出 Web服务器IO的整个详细过程 (1)客户发起请求到服务器网卡: (2)服务器网卡接受到请求后转交给内核 ...
- 熊猫分布密度制图(ArcPy实现)
一.背景 大熊猫是我国国家级珍惜保护动物,熊猫的生存必须满足一定槽域(独占的猎食与活动范围)条件.因此,科学准确的分析熊猫的分布情况,对合理制定保护措施和评价保护成效具有重要意义. 二.目的 通过练习 ...