求最长回文子串(马拉车/Manacher‘s )算法
马拉车算法背景介绍
马拉车算法(Manacher’s Algorithm)是一种用于在 线性时间复杂度(O(n))内找到一个字符串中最长回文子串的高效算法。该算法由 Glenn Manacher 在 1975 年提出,并在论文《A New Linear-Time “On-Line” Algorithm for Finding the Smallest Initial Palindrome of a String》中发表。
核心思想:利用回文的对称性,避免重复计算,通过维护一个“中心”和“右边界”来优化查找过程。
预处理技巧:通过在字符之间插入特殊符号(如 #)统一处理奇偶长度的回文。
为什么叫“马拉车”?中文名称“马拉车”是 “Manacher” 的音译,而非与“马车”相关。
算法优势:传统暴力方法需要 O(n²) 时间,而 Manacher 算法仅需 O(n) 时间和 O(n) 空间。
广泛应用于字符串处理、竞赛编程(如 LeetCode 相关题目)及生物信息学等领域。
如果需要具体的算法实现或论文细节,可以进一步查阅原始论文或相关算法教材。
1 求最长回文子串(马拉车/Manacher‘s )算法
马拉车算法将字符串中的最长回文子串的时间复杂度从n^2 降到线性,该算法主要有两个步骤:分别为字符预处理与计算回文半径数组
1.1 字符预处理
字符预处理就是对原始字符串中的字符之间插入分隔符
这样处理有两个好处:
- 将原先所有偶数个或者奇数个的回文字符串转化为奇数个,便于后面回文半径数组的计算
- 首尾添加两个不同的其他字符,这样在代码编写时可以不用处理边界问题(当然这部分也可以省略)
1.2 计算回文半径数组
用radius表示回文半径数组,radius[i]表示 以i位置为中点,向字符两边扩散,所能构成的最大回文字符串的半径
如下图所示,字符c为中点所构成的伞的半径为3(不包括中心点),即radius[4] = 3,实际上这个radius[4] = 3 也表示原始字符上对应的回文字符的长度,故只要把radius数组求出,就能求出最长回文子串
这里我们需要使用两个变量r,c用来分别用来记录当前遇到的伞所能覆盖的最远的位置,以及对应伞中中心所处的位置。
比如求radius[5]的值时,由于i = 5 在 完全在radius[4]所表示的伞下,那么根据回文字符串的对称性,则可以直接得出 radius[5] = radius[3]
求radius[6]时,由于radius[6]与 radius[2] 处于对称位置但是radius[6]所表示的伞刚好位于radius[4]所表示的伞的边界,故可以得出radius[6] >= radius[2],故这里还需要重新求出 radius[6]的值
备注:
使用回文半径数组的好处,就是如果存在伞完全在某个伞的下面,就不用重新该伞的半径,节省计算时间。