Manacher算法(马拉车算法)
参考:https://www.cnblogs.com/xiuyangleiasp/p/5070991.html
先了解下数组P[i],id,mx的含义,下面的红字部分
Manacher算法利用一个辅助数组P[i]表示以字符Str[i]为中心的最长回文子串的最右(左)字符到Str[i]的距离(包括Str[i])
以abbc为例,首先预处理变成:$#a#b#b#c# (预处理是为了便于处理)可以发现经过预处理后以字母为中心的最长回文串的长度都为奇数
因为字母两边的都是#。
i 0 1 2 3 4 5 6 7 8 9
str | $ | # | a | # | b | # | b | # | c | # |
p[i] | 1 | 1 | 2 | 1 | 2 | 3 | 2 | 1 | 2 | 1 |
以这段来说
对于中间的#来说,最长回文串到中点#(包括中点的长度)的长度为3,即上面有颜色的部分的长度,即p【5】=3
同时也可以发现
P数组有一个性质:P[i]-1是该回文子串在原来字符串中的长度。
例如对于上面中#b#b#这段,这段以中间的“#”为中心,p[5]=3,p[5]-1=2,恰好是bb的长度
假如我们知道p[i]数组,进而求得最大值,然后-1就是该字符串的最长回文串了。接下来是P数组的计算
P数组的计算
如何计算P[i]呢?首先从左至右依次计算P[i],但计算P[i]时,P[j](j<i)已经计算完毕。增加两个辅助变量id和mx,其中id表示最大回文子串中心的位置,mx=id+P[id],即回文子串的边界。
由于P[i]数组是从左往右遍历,这里我们必须得理解id和mx的含义。这里在强调下这三个含义
id表示最大回文子串中心的位置 mx=id+P[id],即回文子串的边界
P[i]表示以字符Str[i]为中心的最长回文子串的最右(左)字符到Str[i]的距离(包括Str[i])
我们先理解下:已知下图中i-6~i是以id为中心的最长回文子串,也就是说str【i-7】!=str【i+1】;根据mx=id+P[id],id指向i-3,由于P[i]表示以字符S[i]为中心的最长回文子串的最右(左)字符到S[i]的距离(包括S[i]),所以P[id]=4,即id+P[id]=4+(i-3)=i+1;即mx指向i+1,可以看出mx指向的位置并不在以id为中心的最长回文串中,同时mx与mx的对称点指向的字符是不相等的
当我们遍历到 i 时,
由于mx指向的位置并不在以id为中心的最长回文串中,所以可以对i与mx的比较分成两种情况讨论,
一种是i在回文串中的情况,即i<mx;
另一种是i不在回文串中的情况,即i>=mx
i<mx
令j=2*id-i,即j为i关于id的对称点。可以对照上图中,id=i-3,i关于id的对称点是i-6,就满足i-6==2*id-i;
由于是从左往右计算p[i],故此时p[ j ]已经计算好了,现在要做的事情是如何利用已经算好的p[ j ] 来更新p[ i ],从而提高效率。
首先我们需要一个参照量,它的含义是表示从i到 以id为中心的最长回文串右边界的 长度(包括i这个点),mx表示的是右边界,上面已经提到mx指向的字符不在以id为中心的回文串中,长度就是: i+1到mx-1这段的长度(含两端)+中点i =(mx-1-(i+1)+1)+1 =mx-i
现在就是将p[ j ]与这个参照量 mx-i 相比较
当P【 j 】>mx-i时,说明以 j 为中心的回文字串有部分超出了以id为中心的回文子串,而超出的部分(下图中的1部分)关于id的对称部分(下图中4部分)必定>=mx,,可知1,2,3部分都对应相等,而之前讲过mx与mx的对称点指向的字符是不相等的,说明1与4部分不对应相等,所以我们所能确保的是 以i为中心,P【i】至少为mx-i (为什么说是至少呢,因为p[ j ]已经帮了很大的忙了,剩下的只能靠我们自己朝两端遍历(下面会讲))
当P【 j 】<=mx-i 时,以Str[j]为中心的回文子串全包含在以Str[id]为中心的回文子串中,基于对称性可知,即下图中颜色相同的对称相等,所以P【i】=P【j】=P【2*id - i】
综上所述,可以得出结论:如果i<mx,则P[i]至少等于min(P[2*id-i],mx-i)。这里是将上面两种情况放在一起考虑,然后在向两边延伸判断(就是下面while语句)。(当然也可以将上面的两种情况分开讨论,可以发现情况二P【 j 】<=mx-i 是不需要向两边延伸判断的。这里将这两种情况放在一起是为了简便些。)
i>=mx
如果i比mx大,则说明对于以S[i]为中心的回文子串还有一部分没有匹配,由于无法对P[i]做更多的假设,只能先令P[i]=1,然后在后续进行相关匹配。
--------
i<mx和i>=mx两种情况用代码实现:
if(mx>i)p[i]=min(p[2*id-i],mx-i);
elsep[i]=1;
以i为中心向两端延伸判断:然后以i中心,往两边延伸,直到两边对称的字符不相等;由于之前以算出i-P【i】+1到i+P【i】-1这段已是回文字串,只需从i-P【i】向左,i+P【i】向右
用代码实现:
while(str[i-p[i]]==str[i+p[i]]) p[i]++;
最后更新mx与id,若i+P[i]>mx,说明以i为中心的回文字串超过的边界mx,就需要更新
实现代码:
if(i+p[i]>mx)
{mx=i+p[i];id=i;
}
这样P【i】数组就求出来了
完整代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
char str[2010];
int p[2500];
int main()
{while(scanf("%s",str)==1){int len=strlen(str);memset(p,0,sizeof(p));//预处理for(int i=len;i>=0;i--){str[2*i+2]=str[i];str[2*i+1]='#';}str[0]='$';int mx=0;int id=0;int res=0;for(int i=0;i<=2*len+1;i++){if(mx>i)p[i]=min(p[2*id-i],mx-i);elsep[i]=1;while(str[i-p[i]]==str[i+p[i]]) p[i]++;if(i+p[i]>mx){mx=i+p[i];id=i;}}//输出P数组for(int i=0;i<=2*len+1;i++)printf("%d ",p[i]);printf("\n");}return 0;}
Manacher算法(马拉车算法)相关推荐
- Manacher Algorithm马拉车算法详解
Manacher Algorithm马拉车算法详解 链接:https://www.zhihu.com/question/37289584/answer/465656849 中心扩展算法 我们先来看一个 ...
- Manachar算法(马拉车算法):快速求取最长回文子串
当我们求取最长回文子串时,常见的方法就是中心扩散法,即从字符中心出发,向两边对比,检查是否相等,若等于,则继续检查,并使当前字符中心对应的最长回文子串长度加一,否则,结束该字符中心的回文检查,比较与当 ...
- 【回文串1 动态规划 马拉车算法】LeetCode 5. Longest Palindromic Substring
LeetCode 5. Longest Palindromic Substring LeetCode中与回文串相关的免费的题目共有15道(5, 9, 125, 131, 132, 214, 234, ...
- 最长回文 HDU - 3068(求最长回文串的长度【马拉车算法Manacher】)
马拉车算法 Manacher's Algorithm 是用来查找一个字符串的最长回文子串的线性方法,由一个叫 Manacher 的人在 1975 年发明的,这个方法的最大贡献是在于将时间复杂度提升到了 ...
- Manacher's Algorithm 马拉车算法(最长回文串)
这个马拉车算法Manacher's Algorithm是用来查找一个字符串的最长回文子串的线性方法,由一个叫Manacher的人在1975年发明的,这个方法的最大贡献是在于将时间复杂度提升到了线性,这 ...
- 【HDU - 3068】最长回文(Manacher算法,马拉车算法求最长回文子串)
题干: 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组case,不超过120组 ...
- 字符串-Manacher算法(你知道马拉车算法吗?)
文章目录 原理 奇偶问题 p[]数组 马拉车求p[] 模板 例题 P3805 [模板]manacher算法 P1659 拉拉队排练 原理 马拉车算法当然不是马拉着车的奇奇怪怪的东西,是Manacher ...
- manacher算法详解(马拉车算法)
马拉车算法 Manacher算法是由题目"求字符串中最长回文子串的长度"而来.比如 abcdcb 的最长回文子串为 bcdcb ,其长度为5. 回文:正着念,反着念都一样 暴力解不 ...
- 【算法】Manacher(马拉车)算法
原jekyll 2019-09-07 Manacher's Alogrithm,中文名叫马拉车算法,是一位叫Manacher的人在1975年提出的一种算法,解决的问题是求最长回文子串,算法的神奇之处就 ...
- Manacher马拉车算法求最长回文子串
终于把马拉车算法搞明白了!赶紧记录一下. 这个算法用于查找一个字符串的最长回文子串 马拉车算法依次给数组p[i]赋值,马拉车算法的本质就是在每次给数组p[i] 赋值时尝试进行偷懒 例如,当要给p[6] ...
最新文章
- 经典 | 吴恩达《机器学习落地应用指南》(30页ppt)
- 对话系统(四)- RNN
- lua 求table长度和判断空
- python variable_PyTorch中的Variable变量详解
- C++学习——类的初始化
- Zookeeper应用:服务端上下线
- Eclipse安装Alibaba Cloud Toolkit并连接阿里云云数据库
- java x%y_java中的运算符
- 团队项目:过山车游戏的设想
- Spring MVC实现Junit Case
- Maven学习总结(36)——Apache Maven 3.5.0抢鲜看
- HDU5686 Problem B【递推】
- 笔记本安装CentOS环境
- 超级管理器Android,超级文件管理器官方最新版下载-超级文件管理器 安卓版v5.5.2-PC6安卓网...
- Android解决手机图片压缩后旋转问题
- [高通SDM450][Android9.0]CTA认证--Android6.0以下应用默认不授权
- Windows.old可以删除吗?
- UML软件开发与建模工具Enterprise Architect发布最新版本v15.2
- 虚拟化最大的市场将出现在3G手机领域
- Linpack测试简介
热门文章
- 一台 ZXHN F650(GPON ONU) 学习小记
- 百度联合清华发布国内首个基于AI实践的产业智能化白皮书
- 柳州计算机一级考试报名时间,2021计算机考试报名时间和考试时间
- CVX用户指南之求解器
- layui的treeTable插件表格树表格行单击点击事件绑定不生效
- 在word里批量插入由文件创建对象,word宏定义批量插入对象
- 通达OA前台任意用户登录漏洞复现
- 仓库货位卡标识牌_怎样正确使用仓库货位卡?来看看这三点
- TAOCP--MIX环境准备
- oracle的dbv命令,DBV(DBVERIFY)工具