给定一个字符串,返回最长子回文串,输入的字符串最大长度不超过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