题目描述
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
中间扩散法
class Solution:
def longestPalindrome(self, s: str) -> str:
if len(s)==1 or not s:
return s
max_r=1
index_r=0
new="#"+"#".join(s)+"#"
r=[1]*len(new) #储存每一个点扩散出去的半径
for i in range(len(new)):
while i-r[i]>0 and i+r[i]<len(new) and new[i-r[i]]==new[i+r[i]]:# 增加半径
r[i]+=1
if max_r<r[i]:
max_r=r[i]
index_r=i
max_r-=1
return new[index_r-max_r:index_r+max_r+1].replace("#","")
每两个元素之间都插入一个"#",这样子来避免奇数和偶数的分类讨论,只需要在结尾的时候消除所有的"#"就好了
执行用时 :4752 ms, 在所有 Python3 提交中击败了27.41%的用户
内存消耗 :13.5 MB, 在所有 Python3 提交中击败了31.66%的用户
中间扩散法—改
class Solution:
def longestPalindrome(self, s: str) -> str:
if len(s)==1 or not s:
return s
max_r=1
index_r=0
zd=1
mx=0
new="#"+"#".join(s)+"#"
r=[1]*len(new) #储存每一个点扩散出去的半径
for i in range(len(new)):
if i<max: #如果是在之前浏览过的地方
if r[2*zd-i]<mx-i:#如果左边对应位置元素半径不超过大半径
r[i]=r[2*zd-i]
else: #如果左边对应位置元素半径超过了大半径,需要对右边多出部分进行检验
r[i]=mx-i
while i-r[i]>0 and i+r[i]<len(new) and new[i-r[i]]==new[i+r[i]]:# 增加半径
r[i]+=1
if i+r[i]>mx: #如果浏览到了没浏览过的,更新最近一次的中点和半径
mx=i+r[i]
zd=i
if max_r<r[i]: #记录最长的回文子串中点和半径
max_r=r[i]
index_r=i
max_r-=1
return new[index_r-max_r:index_r+max_r+1].replace("#","")
多了一个对于对称点半径的使用,减少了计算的数量。
执行用时 :104 ms, 在所有 Python3 提交中击败了93.28%的用户
内存消耗 :13.3 MB, 在所有 Python3 提交中击败了31.71%的用户