以下内容转载自:传送门

源于这两篇文章: 
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. 【优秀作业】粒子群算法(Python)
  2. iPhone开发:Objective-c中@property声明时的参数释疑
  3. mysql设置了utf8mb4还是报错_第07期:有关 MySQL 字符集的 SQL 语句
  4. @ConfigurationProperties和@Value 注入
  5. esp8266 擦拭_【一起玩esp8266】flash的擦除方法——专治疑难杂症
  6. C++基础05-类构造函数与析构函数
  7. javascript回调函数及推论
  8. 数据分析工具R和RStudio入门介绍
  9. pytorch之参数的初始化
  10. PLSQL Developer 64位下载
  11. 谷歌地图的离线地图下载
  12. 无人驾驶入门1:无人驾驶概览
  13. MAR DASCTF 2021
  14. 利用C语言写一个等额本息的还款计算器。
  15. 2021-05-12 MongoDB面试题 什么情况下需要用到MongoDB的分片
  16. 正则表达式在线生成工具
  17. 软件质量与测试--第六周作业 软件测试与评估
  18. IDEA中对Git的常规操作(合并,提交,新建分支,更新)
  19. Spring Security + JWT实现权限管理
  20. vue put 提交 400 Bad Request(有时候可以提交成功)

热门文章

  1. 干货丨常用JS前端开发框架有哪些?
  2. java中List<?>是什么意思?
  3. win10语音语言服务器,win10系统:朗读女语音库(发音人)安装方法说明
  4. system verilog编程题_拼多多2020校招部分算法编程题合集
  5. 启动之后自己关闭_如何关闭Mac开机总是要输入密码?
  6. python动态获取cookie_看到很多人求助python 我也求助一下如何写cookie的获取和登录吧...
  7. 如何让oracle用户不过期,Oracle用户密码设为不过期的两种方法
  8. mysql无法添加或更新子行_MYSQL:错误:无法添加或更新子行:外键约束失败
  9. python3记录(2)— if __name__ == '__main__'
  10. Matlab:批量文件命名