以下内容转载自:传送门

源于这两篇文章: 
http://blog.csdn.net/ggggiqnypgjg/article/details/6645824
http://zhuhongcheng.wordpress.com/2009/08/02/a-simple-linear-time-algorithm-for-finding-longest-palindrome-sub-string/

首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一个特殊的符号。比如 abba 变成 #a#b#b#a#, aba变成 #a#b#a#。 为了进一步减少编码的复杂度,可以在字符串的开始加入另一个特殊字符,这样就不用特殊处理越界问题,比如$#a#b#a#(注意,下面的代码是用C语言写就,由于C语言规范还要求字符串末尾有一个'\0'所以正好OK,但其他语言可能会导致越界)。

下面以字符串12212321为例,经过上一步,变成了 S[] = "$#1#2#2#1#2#3#2#1#";

然后用一个数组 P[i] 来记录以字符S[i]为中心的最长回文子串向左/右扩张的长度(包括S[i],也就是把该回文串“对折”以后的长度),比如S和P的对应关系:

S  #  1  #  2  #  2  #  1  #  2  #  3  #  2  #  1  #
P  1  2  1  2  5  2  1  4  1  2  1  6  1  2  1  2  1
(p.s. 可以看出,P[i]-1正好是原字符串中回文串的总长度)

  

那么怎么计算P[i]呢?该算法增加两个辅助变量(其实一个就够了,两个更清晰)id和mx,其中 id 为已知的 {右边界最大} 的回文子串的中心,mx则为id+P[id],也就是这个子串的右边界。

然后可以得到一个非常神奇的结论,这个算法的关键点就在这里了:如果mx > i,那么P[i] == MIN(P[2 * id - i], mx - i)。就是这个串卡了我非常久。实际上如果把它写得复杂一点,理解起来会简单很多:

//记j = 2 * id - i,也就是说 j 是 i 关于 id 的对称点(j = id - (i - id))
if (mx - i > P[j]) P[i] = P[j];
else /* P[j] >= mx - i */P[i] = mx - i; // P[i] >= mx - i,取最小值,之后再匹配更新。

当然光看代码还是不够清晰,还是借助图来理解比较容易。

当 mx - i > P[j] 的时候,以S[j]为中心的回文子串包含在以S[id]为中心的回文子串中,由于 i 和 j 对称,以S[i]为中心的回文子串必然包含在以S[id]为中心的回文子串中,所以必有 P[i] = P[j],见下图。

当 P[j] >= mx - i 的时候,以S[j]为中心的回文子串不一定完全包含于以S[id]为中心的回文子串中,但是基于对称性可知,下图中两个绿框所包围的部分是相同的,也就是说以S[i]为中心的回文子串,其向右至少会扩张到mx的位置,也就是说 P[i] >= mx - i。至于mx之后的部分是否对称,就只能老老实实去匹配了。

对于 mx <= i 的情况,无法对 P[i]做更多的假设,只能P[i] = 1,然后再去匹配了。

于是代码如下:

//输入,并处理得到字符串s
int p[1000], mx = 0, id = 0;
memset(p, 0, sizeof(p));
for (i = 1; s[i] != '\0'; i++)
{p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;while (s[i + p[i]] == s[i - p[i]]) p[i]++;if (i + p[i] > mx){mx = i + p[i];id = i;}
}
//找出p[i]中最大的

  

转载于:https://www.cnblogs.com/ZhaoxiCheung/p/6826620.html

(转载)Manacher'sAlgorithm: O(n)时间求字符串的最长回文子串相关推荐

  1. 【回文字符串】 最长回文子串O(N) Manacher算法

    原理讲的清晰:Manacher's ALGORITHM: O(n)时间求字符串的最长回文子串 注意: ①动态生命P[]和newStr数组后,不要忘记delete[] //其实这是基本的编码习惯 ②最终 ...

  2. 算法笔记-问题 A: 【字符串】最长回文子串

    问题 A: [字符串]最长回文子串 题目描述 输入一个字符串,求出其中最长的回文子串.子串的含义是:在原串中连续出现的字符串片段.回文的含义是:正着看和倒着看相同.如abba和yyxyy.在判断回文时 ...

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

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

  4. 【字符串】最长回文子串 ( 蛮力算法 )

    文章目录 一.回文串.子串.子序列 二.最长回文子串 1.蛮力算法 2.时间复杂度最优方案 一.回文串.子串.子序列 " 回文串 ( Palindrome ) " 是 正反都一样的 ...

  5. 怎么判断一个字符串的最长回文子串是否在头尾_LeetCode5:最长回文子串

    最长回文子串问题是一个比较经典的题目,且字符串的处理问题也比较重要,这里实现了几种可行的方法,写了ac的表示可以通过,有的是可运行但是会超时或者是超过内存限制. 一:优化的暴力和暴力解 1.1 算是优 ...

  6. 怎么判断一个字符串的最长回文子串是否在头尾_【Leetcode每日打卡】最长回文串...

    干货预警:所有文章都会首发于我的公众号[甜姨的奇妙冒险],欢迎watch. 一.来历: 力扣从3月开始开启了每日一题打卡活动,于是跟风加入了打卡大军,这两天写评论.发题解,没想到反响还不错,收到了来自 ...

  7. 怎么判断一个字符串的最长回文子串是否在头尾_回文自动机入门

    缘起 回文自动机(Palindrome auto machine PAM,有些地方称之为回文树)是回文问题的大杀器~  本文使用一道很简单的题目入门这个精巧的数据结构. hdu 2163 Palind ...

  8. 【字符串】最长回文子串 ( 动态规划算法 ) ★

    文章目录 一.回文串.子串.子序列 二.最长回文子串 1.动态规划算法 2.动态规划算法代码示例 一.回文串.子串.子序列 " 回文串 ( Palindrome ) " 是 正反都 ...

  9. Codeup-问题 A: 【字符串】最长回文子串

    题目描述 输入一个字符串,求出其中最长的回文子串.子串的含义是:在原串中连续出现的字符串片段.回文的含义是:正着看和倒着看相同.如abba和yyxyy.在判断回文时,应该忽略所有标点符号和空格,且忽略 ...

最新文章

  1. 数据结构和算法笔记1 算法的定义,特性,设计要求
  2. 12款最佳的 WordPress 语法高亮插件推荐
  3. ASP.NET_ASP.NET Cookies
  4. SpringSocial业务系统与社交网站的绑定与解绑
  5. 使用C++11封装线程池ThreadPool
  6. 图像处理(8) : 模板匹配
  7. python爬虫代码示例视频教学-清华学霸尹成Python爬虫教学视频
  8. Python 身份证校验代码
  9. 解决360N4S骁龙版在国外使用碰到的问题,附详细root教程
  10. pdf.js、pdfobject.js实现pdf文件预览
  11. 程序员,对自己好一点
  12. 如何注册Gitlab/被墙如何注册
  13. Unity WebGL与浏览器脚本交互
  14. 循序渐进学Java day1
  15. ionic 实现广告图片无限滚动标签介绍
  16. 撼龙图怎么开鸿蒙炁灵,一人之下藏金图技巧-一人之下撼龙藏金图高概率出绝世炁灵技巧...
  17. ASWEET项目实施日志
  18. 盘点八大虚拟桌面基础架构(VDI)协议
  19. Hgame-Week1
  20. word里双横线怎么打_word文档横线怎么打

热门文章

  1. 前端开发基础知识整理--web综合篇
  2. 前端遇到瓶颈了怎么办?
  3. 2020年前端如何适应大环境,发展的前途与趋势是怎么样的?
  4. 刷新按钮_处理数据透视表的隐藏选项(四):固定报表刷新前后的列宽和格式...
  5. influx没有web_influxdb 安装及简单使用
  6. android 蓝牙与单片机通信原理图,手机蓝牙与HC-06蓝牙模块控制单片机程序加APP...
  7. raid硬盘序列号_磁盘阵列出现坏盘,如何正确更换硬盘?
  8. linux 下 svn的安装和使用
  9. mysql 安装、建库、导入导出数据
  10. CSS(网页样式语言)基础,网页CSS设计样式基础知识点 小白教程