【马拉车算法】

class Solution:
    def longestPalindrome(self, A: str) -> str:
        # 首位填其他字符,是的回文串始终是奇数,不用考虑偶数情况
        n=len(A)
        s="#"+"#".join(list(A))+"#"
        # 使用臂长代表回文串半径,初始值为1,臂长-1就是所求回文串长度
        n=2*n+1
        arms=[1]*n
        # 记录包含最右边的回文串中间值及其最右边的索引
        # 因为遍历过最右的索引不会再被遍历,所以复杂度为O(n)
        max_mid,max_ind=-1,-1
        ans=0
        res=(0,0)
        for i in range(n):
            # 更新逻辑是,与max_mid对称位置的臂长加上i仍然够不到最右索引,这里是不包含的,包含就说明够到了,则当前臂长直接等于对称点臂长,否则为i够到最右索引处的长度,然后在进行扩展。
            if arms[2*max_mid-i]+i<max_ind:
                arms[i]=arms[2*max_mid-i]
            else:
                arms[i]=max_ind-i+1
                # 这里同扩展方法
                l,r=i-arms[i],i+arms[i]
                while l>=0 and r<n and s[l]==s[r]:
                    l-=1
                    r+=1
                    arms[i]+=1
                if arms[i]>ans:
                    ans=arms[i]-1
                    res=(l+1,r-1)
                max_mid=i
                max_ind=r-1
        return s[res[0]:res[1]+1].replace("#","")

(1)首先是将奇偶两种情况转成一种情况,用到了类似于奇数+偶数=奇数的思想。

(2)很多,包括动态规划首先需要思考的就是从最右结果开始,后面的结果如何从前面推导出来。这里维护了最右索引和对应的中心点。如果每次i即便加上对称点臂长也无法够到最大索引,明显它也无法够到,更新臂长即可。如果够得到就需要重新扩展了,然后更新臂长,最右索引及其对应中心点。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值