参考: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算法(马拉车算法)相关推荐

  1. Manacher Algorithm马拉车算法详解

    Manacher Algorithm马拉车算法详解 链接:https://www.zhihu.com/question/37289584/answer/465656849 中心扩展算法 我们先来看一个 ...

  2. Manachar算法(马拉车算法):快速求取最长回文子串

    当我们求取最长回文子串时,常见的方法就是中心扩散法,即从字符中心出发,向两边对比,检查是否相等,若等于,则继续检查,并使当前字符中心对应的最长回文子串长度加一,否则,结束该字符中心的回文检查,比较与当 ...

  3. 【回文串1 动态规划 马拉车算法】LeetCode 5. Longest Palindromic Substring

    LeetCode 5. Longest Palindromic Substring LeetCode中与回文串相关的免费的题目共有15道(5, 9, 125, 131, 132, 214, 234, ...

  4. 最长回文 HDU - 3068(求最长回文串的长度【马拉车算法Manacher】)

    马拉车算法 Manacher's Algorithm 是用来查找一个字符串的最长回文子串的线性方法,由一个叫 Manacher 的人在 1975 年发明的,这个方法的最大贡献是在于将时间复杂度提升到了 ...

  5. Manacher's Algorithm 马拉车算法(最长回文串)

    这个马拉车算法Manacher's Algorithm是用来查找一个字符串的最长回文子串的线性方法,由一个叫Manacher的人在1975年发明的,这个方法的最大贡献是在于将时间复杂度提升到了线性,这 ...

  6. 【HDU - 3068】最长回文(Manacher算法,马拉车算法求最长回文子串)

    题干: 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.  回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组case,不超过120组 ...

  7. 字符串-Manacher算法(你知道马拉车算法吗?)

    文章目录 原理 奇偶问题 p[]数组 马拉车求p[] 模板 例题 P3805 [模板]manacher算法 P1659 拉拉队排练 原理 马拉车算法当然不是马拉着车的奇奇怪怪的东西,是Manacher ...

  8. manacher算法详解(马拉车算法)

    马拉车算法 Manacher算法是由题目"求字符串中最长回文子串的长度"而来.比如 abcdcb 的最长回文子串为 bcdcb ,其长度为5. 回文:正着念,反着念都一样 暴力解不 ...

  9. 【算法】Manacher(马拉车)算法

    原jekyll 2019-09-07 Manacher's Alogrithm,中文名叫马拉车算法,是一位叫Manacher的人在1975年提出的一种算法,解决的问题是求最长回文子串,算法的神奇之处就 ...

  10. Manacher马拉车算法求最长回文子串

    终于把马拉车算法搞明白了!赶紧记录一下. 这个算法用于查找一个字符串的最长回文子串 马拉车算法依次给数组p[i]赋值,马拉车算法的本质就是在每次给数组p[i] 赋值时尝试进行偷懒 例如,当要给p[6] ...

最新文章

  1. 经典 | 吴恩达《机器学习落地应用指南》(30页ppt)
  2. 对话系统(四)- RNN
  3. lua 求table长度和判断空
  4. python variable_PyTorch中的Variable变量详解
  5. C++学习——类的初始化
  6. Zookeeper应用:服务端上下线
  7. Eclipse安装Alibaba Cloud Toolkit并连接阿里云云数据库
  8. java x%y_java中的运算符
  9. 团队项目:过山车游戏的设想
  10. Spring MVC实现Junit Case
  11. Maven学习总结(36)——Apache Maven 3.5.0抢鲜看
  12. HDU5686 Problem B【递推】
  13. 笔记本安装CentOS环境
  14. 超级管理器Android,超级文件管理器官方最新版下载-超级文件管理器 安卓版v5.5.2-PC6安卓网...
  15. Android解决手机图片压缩后旋转问题
  16. [高通SDM450][Android9.0]CTA认证--Android6.0以下应用默认不授权
  17. Windows.old可以删除吗?
  18. UML软件开发与建模工具Enterprise Architect发布最新版本v15.2
  19. 虚拟化最大的市场将出现在3G手机领域
  20. Linpack测试简介

热门文章

  1. 一台 ZXHN F650(GPON ONU) 学习小记
  2. 百度联合清华发布国内首个基于AI实践的产业智能化白皮书
  3. 柳州计算机一级考试报名时间,2021计算机考试报名时间和考试时间
  4. CVX用户指南之求解器
  5. layui的treeTable插件表格树表格行单击点击事件绑定不生效
  6. 在word里批量插入由文件创建对象,word宏定义批量插入对象
  7. 通达OA前台任意用户登录漏洞复现
  8. 仓库货位卡标识牌_怎样正确使用仓库货位卡?来看看这三点
  9. TAOCP--MIX环境准备
  10. oracle的dbv命令,DBV(DBVERIFY)工具