leetcode 第5题(最长子回文串)

358 阅读2分钟

给定一个字符串,返回最长子回文串,输入的字符串最大长度不超过1000

例:

输入 : 'babad'

返回:'bab' or 'aba'


解法1 :(暴力解法, 容易理解, 时间复杂度o(n^2))

class Solution:
    def longestPalindrome(self, s: str) -> str:
        result = ''
        for i in range(len(s)):
            for k in range(i + 1, len(s) + 1):
                if s[i:k] == s[i:k][::-1] and len(s[i:k]) > len(result):
                    result = s[i:k]
        
        return result


解法2:

class Solution:
    def longestPalindrome(self, s):
        s_reversed = s[::-1]
        if s == s_reversed:
            return s

        cur = s_max = s[0]
        for i in range(1, len(s) + 1):          # +1 to check the last letter
            if cur in s_reversed:               # does it have potential to become palindrome?
                if cur == cur[::-1]:            # is it palindrome?
                    if len(cur) >= len(s_max):  # is it the longest palindrome found so far
                        s_max = cur
            else:                               # does not have palindrome potential. strip the left side to fix it
                while cur not in s_reversed:
                    cur = cur[1:]

            if i < len(s):
                cur += s[i]

        return s_max

    #此解法由roman8422 上传


解法2能够快速排除不满足回文的子串,性能比解法1 块10倍左右(基于题目给定条件)


解法3:Manacher's Algorithm(马拉车算法)

def longestPalindrome(s):
    """
    :type s: str
    :rtype: str
    """
    s = '$#' + '#'.join(list(s)) + '#'    # 预处理
    p = [0] * len(s)
    longestInfo = [0,0]
    i,currRes,currMax = 1,0,0  # 由于s[0]是$,所以i从1开始取值。id和mx分别换了个名字currRes和currMax
    while i < len(s):
        if i > currMax:    # i已经超出mx的情况
            p[i] = 1
        else:    # i未超出mx,再分成两种情况,体现在min函数中
            j = 2*currRes - i
            p[i] = min(p[j],currMax-i)
        # 此时p[i]并不一定已经正确,除了决定p[i]=p[j],其他两个分支都只是给了p[i]一个基准值
        while i-p[i]>0 and i+p[i]<len(s) and s[i-p[i]] == s[i+p[i]]:
            # 进行一个个字符向外扩散的回文性检查
            # 注意为了防止越界访问,还要有边界判断条件
            p[i] += 1
        # 这时p[i]才得到了最终确定的值 接下来就是将其相关属性与已有的currRes和currMax比较,看是否需要更新
        if i + p[i] > currMax:
            # 更新id和max
            currRes = i
            currMax = i + p[i]

        if p[i] > longestInfo[1]:
            # 更新最终结果值
            longestInfo = i,p[i]

        i += 1
    center = longestInfo[0]
    radius = longestInfo[1] - 1    # 注意,半径把对称中心本身算进去了,所以减一
    return s[center-radius:center+radius+1].replace('#','')  # 直接replace去掉所有辅助字符,得到的就是原字符串的结果了。
    #转载出处:https://www.cnblogs.com/franknihao/p/9342907.html