方法一:暴力解法
遍历所有的子串,判断是否为回文字符串
class Solution:
def longestPalindrome(self, s: str) -> str:
if len(s) < 2:
return s
begin = 0
maxlength = 1
for i in range(len(s)-1):
for j in range(i+1, len(s)):
if (j - i + 1 > maxlength) and self.isPalindrome(s, i, j):
maxlength = j - i + 1
begin = i
return s[begin: begin+maxlength]
def isPalindrome(self, chararray: str, left: 'begin index', right: 'end index') -> bool:
while (left < right):
if chararray[left] != chararray[right]:
return False
left += 1
right -= 1
return True
复杂度分析
- 时间复杂度: O ( n 3 ) O(n^3) O(n3)
- 空间复杂度: O ( 1 ) O(1) O(1)
但此解法超出时间限制
方法二:中心扩展算法
遍历字符串中的字符,分别以每个字符、每个字符和下一个字符为中心向两边扩散,寻找最长回文子串。
class Solution:
def longestPalindrome(self, s: str) -> str:
if len(s) < 2:
return s
begin = 0
maxlength = 1
for i in range(len(s)-1):
oddLen = self.expandAroundCenter(s, i, i)
evenLen = self.expandAroundCenter(s, i, i + 1)
maxCurlength = max(oddLen, evenLen)
if maxCurlength > maxlength:
maxlength = maxCurlength
begin = i - (maxCurlength - 1) // 2
return s[begin: begin + maxlength]
def expandAroundCenter(self, chararray: str, left: 'left center index', right: 'right center index') -> int:
length = len(chararray)
while (left >= 0 and right < length):
if chararray[left] == chararray[right]:
left -= 1
right += 1
else:
break
PalindromeLen = right - left - 1 # right - left + 1 - 2
return PalindromeLen
复杂度分析
方法三:动态规划
class Solution:
def longestPalindrome(self, s: str) -> str:
length = len(s)
if length < 2:
return s
begin = 0
maxlength = 1
Palindrome_Matrix = [[False] * length for _ in range(length)]
for i in range(length):
Palindrome_Matrix[i][i] = True # 对角线表示的是单个字符,肯定是回文串
# 先按列,再按行赋值
for j in range(1, length):
for i in range(j):
if s[i] == s[j]:
# 若s[i...j]的长度≤3,则一定为回文串
if j - i < 3:
Palindrome_Matrix[i][j] = True
else:
Palindrome_Matrix[i][j] = Palindrome_Matrix[i+1][j-1]
if Palindrome_Matrix[i][j] and (j - i + 1 > maxlength):
begin = i
maxlength = j - i + 1
return s[begin: begin + maxlength]
复杂度分析
*方法四:Manacher 算法
class Solution:
def longestPalindrome(self, s: str) -> str:
length = len(s)
if length < 2:
return s
# 预处理字符串
new_s = self.adddivider(s, '#')
new_length = len(new_s)
# 回文半径
p = [0 for i in range(new_length)]
# 当前已得到的通过中心扩散法能够扩散到的最右边的下标
maxRight = 0
# maxRight对应的中心点下标
center = 0
begin = 0
maxlength = 1
for i in range(new_length):
if i < maxRight:
# i关于center的对称点
mirror = 2 * center - i
# 状态转移方程
p[i] = min(maxRight - i, p[mirror])
# 尝试使用中心扩散法,更新p[i]的值,注意这一步是与 i > maxRight 的情况结合起来
left = i - (p[i] + 1)
right = i + (p[i] + 1)
while(left >= 0) and (right < new_length) and (new_s[left] == new_s[right]):
p[i] += 1
left -= 1
right += 1
if i + p[i] > maxRight:
maxRight = i + p[i]
center = i
if p[i] > maxlength:
maxlength = p[i]
begin = (i - maxlength) // 2
return s[begin: begin + maxlength]
def adddivider(self, s: str, divider: str) -> str:
new_s = divider
for i in range(len(s)):
new_s += (s[i] + divider)
return new_s
复杂度分析