思路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麻豆出品,必出精品!

京公网安备 11010502036488号