题目描述
方法一:
暴力循环法,找出所有的可能的字符串,再判断是否是回文。
啥比了很长一段时间没想明白,原来是因为s[i:k]的语法是表达s[i]~s[k-1]。
附上惨痛教训无处不print代码,方便像我一样的菜鸡理解。
应该解释的比较清楚了,大家用的时候把print去掉就行。
s = 'babad'
l = len(s)
print("l =",l)
max_length = 0
#将回文字符串定义为一个空字符串
palindromic_sequence = ''
#如果待判定的字符串种只有一个字符,那它必定是回文字符串
if len(s) == 1:
print(s)
#做一个循环,从第一个字符开始检查
for i in range(l):
print("i =",i)
#从第二个字符为末尾,第一个字符为开头形成字符串,也就是依次12,13,14,...,1l
for j in range(i + 1, l):
print("j =",j)
#先假定这个字符串是回文
is_palindromic = True
#k是用来算检查字符串是否是回文的下标,k最大是int((i + j) / 2) + 1
#这是因为如果检查的字符串的字符个数是偶数,由于字符串下标是从0开始的,所以要+1,刚好就是中间位置
#如果是奇数=上一行的偶数+1,因为回文不收最中间的那个字符的影响,所以和偶数的情况一样,向下取整即可
for k in range(i, int((i + j) / 2) + 1):
print("k =",k)
print(s[k],s[j-k+i])
if s[k] != s[j - k + i]:
print(s[k],s[j-k+i])
is_palindromic = False
#不符合条件就退出
break
#(j - i + 1) > max_length是避免空字符
if is_palindromic and (j - i + 1) > max_length:
#这是算回文字符长度
max_length = j - i + 1
palindromic_sequence = s[i:j + 1]
#j+1的原因是s[i:k]的语法是s[i]~s[k-1]
print("palindromic_sequence =",palindromic_sequence)
if palindromic_sequence == '':
palindromic_sequence = s[0]
print(palindromic_sequence)
顺便附上实现的结果。
方法二:
中心枚举法,枚举字符串的中点,而不是从头开始循环。认真看注释啊,写了好久的,应该能看懂的。
class Solution:
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
l = len(s)
max_length = 0
palindromic_sequence = ''
for i in range(l):
#这里分间隔interval为1和0是要区分两种字符个数为奇数或者偶数的回文序列
#interval = 1是奇数的情况,也就是开始循环的这个字符现在是回文字符的中心
#它的左右两边要对称543212345,类似这种情况,1在中间。
interval = 1
while (i - interval) >= 0 and (i + interval) < l:
#上下界不能出
#保证中心左右两边对称
if s[i + interval] == s[i - interval]:
#保证中心左右两边对称
interval += 1
else:
break
interval -= 1
#算长度时要减一,因为你成功对称一次就加了1,而你interval的起始值是1不是0,故要-1
#2 *interval + 1是因为加上中心点的值的位置
if 2 *interval + 1 > max_length:
max_length = 2 *interval + 1
palindromic_sequence = s[i - interval:i +interval + 1]
interval = 0
#interval = 0是回文字符串字符个数为偶数的情况
#偶数的情况就是至少2个字符,所以interval = 0,最中间相邻的两个要相同
#比如32100123这样
if (i + 1) < l:
#这一步是防止它是单字符串
while (i - interval) >= 0 and (i + 1 + interval) < l:
#上下界不能出
if s[i + 1 + interval] == s[i - interval]:
#保证两个中心两边相等,之后就是保证中心左右两边对称
interval += 1
else:
break
interval -= 1
#和奇数的时候同理,但是由于中心的个数变成两个了,所以是+2
if 2 *interval + 2 > max_length:
max_length = 2 *interval + 2
palindromic_sequence = s[i - interval:i + interval + 2]
if palindromic_sequence == '':
#这里是单字符串的情况
palindromic_sequence = s[0]
return palindromic_sequence
方法三:
马拉车(manacher)算法
实在是没看懂代码,算法大致理解,先埋个坑五点交作业把链接附上。
稍微看懂了一点回来补充了,附上带print的代码。
具体讲解可以看第一条的链接
# manacher算法
class Solution:
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
#预处理
t='#'+'#'.join(s)+'#'
print(t)
RL=[0]*len(t)
#生成和t一样长度的全为0的list
print(RL)
MaxRight=0
print("MaxRight =",MaxRight)
pos=0
print("pos =",pos)
# MaxLen=0
for i in range(len(t)):
print("i =",i)
if i<MaxRight:
print("MaxRight =",MaxRight)
# 或者RL[i]=min(RL[2*pos-i], MaxRight-i)
# 上述注释掉的这行代码直接等价于下面5行代码
j=2*pos-i
#j是i关于pos的对称点
print("j =",j)
if MaxRight-i>RL[j]:
RL[i]=RL[j]
print("RL =",RL)
else:
RL[i]=MaxRight-i
print("RL =",RL)
else:
RL[i]=1
print("RL =",RL)
#尝试扩展,注意处理边界
while i-RL[i]>=0 and i+RL[i]<len(t) and t[i-RL[i]]==t[i+RL[i]]:
RL[i]+=1
print("RL =",RL)
#更新MaxRight,pos
if RL[i] >= RL[pos]:
MaxRight = RL[i] + i - 1
print("MaxRight =",MaxRight)
pos = i
print("pos =",pos)
'''
if RL[i]+i-1>MaxRight:
MaxRight=RL[i]+i-1
pos=i
#更新最长回文串的长度
MaxLen=max(MaxLen, RL[i])
return MaxLen-1
'''
a=int((2*pos-MaxRight)/2)
print("a =",a)
b=int(MaxRight/2)
print("b =",b)
return s[a:b]
s = Solution()
a = s.longestPalindrome('abab')
print(a)
https://mp.weixin.qq.com/s/D72qugTLpgITU6IJ1QQERg
https://www.felix021.com/blog/read.php?2040
https://www.bilibili.com/video/av4829276?from=search&seid=8243409683193841648