【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_lenj)已经找到,问如何利用这一信息求之后的索引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]
相关推荐
罗西的思考几秒前
DreamZero 与 DreamDojo:世界模型与策略的分层协同综合分析与对比
人工智能·算法·机器学习
玖玥拾32 分钟前
LeetCode 219 存在重复元素 II
算法·leetcode·哈希算法·散列表
知无不研1 小时前
c语言中循环的介绍与简单应用
c语言·开发语言·算法·循环·for·while
a187927218313 小时前
【算法】动态规划第四篇:背包收官——min 哨兵、计数世界与组合排列分水岭
算法·leetcode·动态规划·dp·01背包·算法讲解·决策合并
2601_962297483 小时前
在python3中、下列输出变量a的正确写法是_2020超星大数据Python免费答案
数据结构·python·算法·编程·字符串操作
辰烨chenye3 小时前
LeetCode Hot 100 题解 · 子串篇
算法·leetcode·职场和发展
辰烨chenye3 小时前
LeetCode Hot 100 题解 · 堆篇
java·算法·leetcode
手写码匠3 小时前
华为云Flexus+DeepSeek征文|DeepSeek 应用监控告警体系实战:从“用户投诉才知道“到“故障前就发现“
人工智能·深度学习·算法·aigc
shehuiyuelaiyuehao4 小时前
算法29,前缀和,除自身以外的数组的乘积
java·数据结构·算法
智购科技自动售货机厂家4 小时前
2026自动售货机设备清洁效果自动验证:从图像比对到评分算法的工程实践~YH
人工智能·算法·计算机视觉