思路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

麻豆出品,必出精品!