最长回文子串(python,动规/马拉车)

最长回文子串

http://www.nowcoder.com/questionTerminal/b4525d1d84934cf280439aeecc36f4af

思路1(动态规划,O(n^2))
从第一个字符往后遍历,把每个字符都当作中心去向两边扩散,依次比较对称位置是否相等,当碰到左右边界停下。注意要分奇偶子串两种情况。

代码1

class Palindrome:
    def getLongestPalindrome(self, A, n):
        def func(A, left, right):
            while left >=0 and right < n and A[left]==A[right]:
                left -= 1
                right += 1
            return right-left-1

        res = 0
        for i in range(n-1):
            res = max(res, func(A, i, i), func(A, i, i+1))
        return res

思路2(马拉车算法,O(n))
在处理最长回文子串的时候,一般教科书上都会提一个线性的算法–Manacher大法,它可以将动态规划情况下的复杂度由n^2的复杂度降到线性。马拉车算法能将奇偶长度的子串归为一类,统一使用上面动态规划用的中心扩展法。它在原字符串中插入特殊字符,例如插入#后原字符串变成'#3#5#5#3#4#3#2#1#'。现在我们对新字符串使用中心扩展发即可,中心扩展法得到的半径就是子串的长度。但是在本题实际操练时,耗时上并没卵用。这里简单看下思路吧。

代码2

class Palindrome:
    def getLongestPalindrome(self, A, n):
        if n <= 1: return n
        # 每个字符之间插入 #
        ss = '$#' + '#'.join([x for x in A]) + '#`'
        p = [1] * len(ss)
        center = 0
        mx = 0
        max_str = ''
        for i in range(1, len(p)-1):
            if i < mx:
                j = 2 * center - i # i 关于 center 的对称点
                p[i] = min(p[j],mx-i)
            # 尝试继续向两边扩展,更新 p[i]
            while ss[i - p[i] ] == ss[i + p[i] ]: # 不必判断是否溢出,因为首位均有特殊字符,肯定会退出
                p[i] += 1
            # 更新中心
            if i + p[i] - 1 > mx:
                mx = i + p[i] - 1
                center = i
            # 更新最长串
            if 2 * p[i]-1 > len(max_str):
                max_str = ss[i - p[i]+1 : i + p[i]]
        maxLen = len(max_str.replace('#', ''))
        return maxLen

麻豆出品,必出精品!

全部评论
哟,麻豆是什么意思呀?可以吃的吗?
2 回复 分享
发布于 2020-09-24 19:50
那个向两边扩散的是动态规划吗,感觉没有那个思想
1 回复 分享
发布于 2021-03-24 17:20
是你吗阿然
点赞 回复 分享
发布于 2020-12-28 14:57
真不错
点赞 回复 分享
发布于 2020-12-25 13:20

相关推荐

Aurora23:属于挂一半,暂时进池子了,隔一段时间没有其他组捞的话就彻底结束了
点赞 评论 收藏
分享
评论
12
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务