【leetcode 5】最长回文子串, Manachers算法

  • 解法一
    枚举每个回文的中心(回文中心可能是一个字符,也可能是两个字符,例子分别是:cac,caac),从这个回文中心出发向两边扩散,直到扩到不能再扩,记录下该回文中心能够产生的最长回文字符串的起始、终止位置;
    与全局最长回文字符串的起始、终止位置比较,记录下最长回文字符串。
python 复制代码
class Solution:
    def expand(self,s,l,r):
        while l>=0 and r<len(s) and s[r]==s[l]:
            l-=1
            r+=1
        return l+1,r-1

    def longestPalindrome(self, s: str) -> str:
        start,end=0,0
        for i in range(len(s)):
            left1,right1=self.expand(s,i,i)
            left2,right2=self.expand(s,i,i+1)
            if right1-left1>end-start:
                start,end=left1,right1
            if right2-left2>end-start:
                start,end=left2,right2
        return s[start:end+1]
    

解法2: Manacher算法

在上面枚举每一个回文中心 向左右两边扩散的解法的基础上,考虑如何复用已经求出来的信息。

现在仅考虑长度为奇数的字符串,

假设以索引j为中心的最长回文字符串(回文字符串的一半的长度为arm_len[j])已经找到,问如何利用这一信息求之后的索引i作为回文中心时的长度?

对于之后的索引i,

  • 首先,求以s[i]为中心时最长回文子串的臂长,记为cur_arm_len
    这个过程分为两个步骤,
    首先,利用之前索引j的回文臂长信息arm_len[j]和目前最长回文子串能够到达的最远位置right,找到以s[i]为中心且不超过当前已知最长回文子串范围时的回文子串的臂长min_arm_len;(注:如果目前已知的以s[j]为中心的回文子串并不能覆盖i,那么arm_len[j]信息没用,所以可以跳过求min_arm_len这一步骤)
    接着,在min_arm_len的基础上,利用方法self.expand,继续向左右探索以s[i]为中心时可能的回文片段,直到不对称为止,并返回回文臂长。
  • 接着,记录以s[i]为中心时最长回文子串的臂长到数组arm_len中;
  • 然后,更新最近一次的已知回文中心j和最近一次的回文子串的最大索引right;
  • 最后,更新全局变量start,end(最长回文子串的起始、末尾位置)。
python 复制代码
class Solution:
    def expand(self,s,l,r):
        while l>=0 and r<len(s) and s[l]==s[r]:
            l-=1
            r+=1
        return (r-l-2)//2  

    def longestPalindrome(self, s: str) -> str:
        start,end=0,0
        s='#'+'#'.join(s)+'#'
        arm_len=[]
        right=-1
        j=-1
        for i in range(len(s)):
            if i<=right:
                i_sym=2*j-i
                min_arm_len=min(right-i,arm_len[i_sym])
                cur_arm_len=self.expand(s,i-min_arm_len,i+min_arm_len)
            else:
                cur_arm_len=self.expand(s,i,i)
            arm_len.append(cur_arm_len)
            if i+cur_arm_len>right:
                right=i+cur_arm_len
                j=i
            if 2*cur_arm_len+1>end-start:
                start,end=i-cur_arm_len,i+cur_arm_len
        return s[start+1:end+1:2]
相关推荐
AI十八式29 分钟前
KDD 2025 顶会最新力作,多变量时间序列预测登顶!
算法·机器学习·支持向量机
Tinatal40 分钟前
map映射到二维数组
开发语言·c++·算法
一只_程序媛1 小时前
【leetcode hot 100 300】最长递增子序列
算法·leetcode·职场和发展
岁ovo寒1 小时前
c++day7
开发语言·c++·算法
Kita~Ikuyo1 小时前
基础数学:线性代数与优化理论
人工智能·线性代数·算法·机器学习
小森77672 小时前
(四)机器学习---逻辑回归及其Python实现
人工智能·python·算法·机器学习·逻辑回归·线性回归
小阳拱白菜3 小时前
蓝桥杯刷题--挖矿
算法·职场和发展·蓝桥杯
补三补四3 小时前
【深度学习基础】——机器的神经元:感知机
人工智能·深度学习·算法·机器学习
100分题库橙子3 小时前
2025年汽车加气站操作工证考试内容
经验分享·职场和发展
ZHW_AI课题组3 小时前
基于线性回归模型的汽车燃油效率预测
算法·汽车·线性回归