【概述】

Manacher 算法又称马拉车算法,用于求最长回文子串。

对于最长回文子串传统的求法的求法是以每个字符为中心,向两边寻找回文子串,在遍历完整个数组后即可得到最长回文子串,其时间复杂度为 O(n^2)

而马拉车算法,将求最长回文子串的时间复杂度提升到了线性,其时间复杂度只有 O(n)

【算法流程】

1.预处理

由于字符串的长度分为奇偶两种,因此对于初始的字符串,在每一个字符的左右都加上一个未在串中出现过的字符,得到一个新的字符数组 newStr[]。

比如:

  • 奇数字符串:bob --> #b#o#b#
  • 偶数字符串:noon --> #n#o#o#n#

这样一来,无论原字符串是奇数个字符还是偶数个字符,处理后的字符串字符的个数都是奇数个,这样就无需分情况讨论了。

2.设置辅助数组

接下来,还需要定义一个辅助数组 p[],其中 p[i] 表示以字符 newStr[i] 为中心的最长回文半径,若 p[i]=1,则该回文子串就是 newStr[i] 本身。

例如:以字符串 abbahopxp 为例

i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
newStr[i] $ # a # b # b # a # h # o # p # x # p #
p[i]   1 2 1 2 5 2 1 2 1 2 1 2 1 2 1 4 1 2 1

可以看出,p[i]-1 即为原字符串中最长回文串的长度。

3.求解辅助数组

首先新增两个变量 mx 与 id,其中 mx 代表以 id 为中心的最长回文串的右边界,即:mx=id+p[id]

假设求以 i 为中心的最长回文半径,即求解 p[i],当 i<mx 时,那么有 p[i] = min(p[2*id-i], mx-i),否则 p[i]=1,其中 2*id-i 为图中的 j 点,即 p[j] 是以 j 为中心的最长回文半径

【复杂度分析】

基于回文串的性质,辅助数组 p[i] 的值基于以下三种情况得出:

1)j 的回文串有一部分在 id 的回文串之外

如上图,黑线为 id 的回文串,i 与 j 关于 id 对称,红线为 j 的回文,紫线为 i 的回文,虚线为以 id 为中心的回文右边界 mx,那么根据 p[i]=mx-i,即紫线的部分,那么可以得出,p[i] 无法得到更大的值

如上图,假设右侧新增的紫色 d 部分是 p[i] 可增加的部分,那么根据回文的性质,也即是说 id 的回文 = 黑线 + a + d,矛盾,假设不成立,因此 p[i] 无法再增加,得到一个更大的值

2)j 回文串全部在 i 内部

如上图,此时 p[i]=p[j],那么可以得出,p[i] 无法得到更大的值

如上图,假设右侧的红线 d 是 p[i] 可增加的部分,那么根据回文的性质,j 的回文 = j 之前的回文 + a + b,矛盾,假设不成立,因此 p[i] 无法再增加,得到一个更大的值

3)i 的回文串右端与 id 的回文串右端重合

如上图,此时 p[i]=p[j],或 p[i]=mx-i,此时 p[i] 可以继续增加,那么有:

while(newStr[i-p[i]]==newStr[i+p[i]]) p[i]++;

根据(1)(2)(3),容易推出 Manacher 算法的最坏情况,即为字符串内全是相同字符的时候,平均访问每个字符 5 次,同理,也容易推出 Manacher 算法的最佳情况,即为字符串内字符各不相同的时候,平均每个字符访问 4 次。

综上,Manacher算法的时间复杂度为 O(n)。

【实现】

char str[N];//原字符串
char newStr[N*2];//预处理后的字符串
int p[N*2];//辅助数组
int init(){//对原字符进行预处理newStr[0]='$';newStr[1]='#';int j=2;int len=strlen(str);for (int i=0;i<len;i++){newStr[j++]=str[i];newStr[j++]='#';}newStr[j] ='\0'; //字符串结束标记return j;//返回newStr的长度
}int manacher(){int len=init();//取得新字符串长度并完成字符串的预处理int res=-1;//最长回文长度int id;int mx=0;for(int i=1;i<len;i++){int j=2*id-i;//与i相对称的位置if(i<mx)p[i]=min(p[j], mx-i);elsep[i]=1;//由于左有'$',右有'\0',不需边界判断while(newStr[i-p[i]] == newStr[i+p[i]])//p[i]的扩大p[i]++;if(mx<i+p[i]){//由于希望mx尽可能的远,因此要不断进行比较更新id=i;mx=i+p[i];}res=max(res,p[i]-1);}return res;
}int main(){while (printf("请输入字符串:\n")){scanf("%s",str);printf("最长回文长度为 %d\n", manacher());}return 0;
}

字符串处理 —— 回文串相关 —— Manacher 算法相关推荐

  1. (回文串)Manacher算法

    (回文串)Manacher算法 标签: ACM 回文串 Manacher 问题描述: 输入一个字符串,求出其中最大的回文子串.子串的含义是:在原串中连续出现的字符串片段.回文的含义是:正着看和倒着看相 ...

  2. 怎么判断一个字符串的最长回文子串是否在头尾_LeetCode 5 迅速判断回文串的Manacher算法...

    本文始发于个人公众号: TechFlow 题意 Given a string s, find the longest palindromic substring in s. You may assum ...

  3. 字符串处理 —— 回文串相关

    [回文串] 回文串,就是一个正读与反读都一样的字符串,比如:abcdcba.zxccxz 等 常见的回文串算法有:求字符串中最长回文串.判断一个字符串是否为回文串.在字符中添加/删除一个字符后是否为回 ...

  4. 字符串处理 —— 回文串相关 —— 求最长回文子串

    [暴力枚举] 求最长回文串最容易的方法就是暴力枚举,求出字符串的每一个子串,然后判断是不是回文,找到最长的那个回文串 求每一个子串的时间复杂度为 O(N^2),判断一个子串是不是回文时间复杂度为 O( ...

  5. 字符串处理 —— 回文串相关 —— 添加/删除字符后是否为回文串

    [问题] 给定一个字符串,问对该字符串,是否能通过添加一个字符后变为回文串. 若可以,输出 YES,否则输出 NO 对于该问题,首先要明白,删除一个字符与添加一个字符在判断回文串中是等价的. [暴力枚 ...

  6. 字符串处理 —— 回文串相关 —— 回文串的判断

    [逐个比较] bool isPalindrome(string str){for(int i=0;i<str.size()/2;i++)if(str[i]!=str[str.size()-1-i ...

  7. 力扣--让字符串成为回文串的最少插入次数

    力扣–让字符串成为回文串的最少插入次数 文章目录 力扣--让字符串成为回文串的最少插入次数 一.题目描述 二.分析 三.代码 相关题目: 腾讯–构造回文:腾讯–构造回文 最长回文子串和回文链表:最长回 ...

  8. 力扣- - 最短回文串(KMP算法)

    力扣- - 最短回文串(KMP算法) 文章目录 力扣- - 最短回文串(KMP算法) 一.题目描述 二.分析之KMP算法 1.暴力法 2.KMP算法 3.next数组求法1:暴力查找最长的前后缀 4. ...

  9. 分割两个字符串得到回文串[抽象--去除具体个性取共性需求]

    抽象 前言 一.分割两个字符串得到回文串 二.双指针 总结 参考文献 前言 抽象去个性留共性,是因为具体个性对于解决问题是个累赘.少了累赘,直击需求,才能进行问题转换或者逻辑转换. 一.分割两个字符串 ...

最新文章

  1. 【从零开始的ROS四轴机械臂控制】(五)- 构建运动控制服务
  2. php中mysql,PHP中的mysql
  3. Canvas 属性,方法
  4. java machine 报错_Eclipse启动时报错:No java virtual machine
  5. 联想android刷机教程视频,联想s939刷机教程(刷官方系统)
  6. 从VC++到GCC移植:谈两者的语法差异
  7. w7电脑蓝屏怎么解决_电脑蓝屏Win32k.sys怎么办
  8. 通向架构师的道路(第十四天)Axis2 Web Service安全之rampart
  9. Oracle内部错误ORA-07445[kpopfr()+339] [SIGFPE]一例
  10. java 的strip_javastript
  11. svg 转换为 pdf (batik 库+fop库)
  12. 南航计算机学院考研的专业课,【南航计算机考研】南航计算机考研经验贴
  13. html实现背景图片自动更换,如何实现在HTML中更换或添加网站背景图片
  14. Python和Numpy的加权抛硬币游戏的概率
  15. 局域网公用一个mysql数据库
  16. Vue刷新、跳转页面的数据保存方法: sessionStorage + Object.assign()
  17. 海思SDK安装过程以及OSDRV编译不成功出现的问题的解决
  18. 微信撤回消息服务器还有存底么,微信更新又来了,撤回消息大变化!还增加“查岗”功能......
  19. 读写文本文件-StreamReader和StreamWriter
  20. 极客日报:​​​字节员工操纵抖音热榜被判刑;微信群聊可直接访问电商外链;JetBrains发布新一代编辑器Fleet

热门文章

  1. 爱因斯坦耗费近十年的最伟大研究,推导出什么神预言?
  2. 从0到1:Python爬虫知识点梳理
  3. 问八股文的公司都是垃圾!?
  4. 原来这就是比 ThreadLocal 更快的玩意
  5. Java基础夺命连环16问
  6. 我还在生产玩 JDK7,JDK 15 却要来了!|新特性尝鲜
  7. 都9012年了,还有人说IntelliJ IDEA不好用?那是因为没掌握这些技巧。
  8. IntelliJ IDEA下的使用git
  9. MySQL进阶篇(01):基于多个维度,分析服务器性能
  10. 总结一些生物成像的 开源图像与插件网站