回文串,即:
nums = 'aba'
print(nums == nums[::-1]) # True 反转该序列后和之前元素相等
这里我们需要找出给定字符串里的最长回文串,即:
nums = 'abcbde'
'bcb' 为 nums 的最长回文串子序列
枚举法
nums = 'babad'
D = dict() # 储存之前出现过的字符串的序列
max_len = 0 # 初始化 回文串的长度
num = nums[0] # 初始化 回文串
for i, s in enumerate(nums):
if s in D:
# 记录字符出现的索引
D[s] += [i]
# 遍历字符s出现的索引
for j in D[s]:
# 判断字符s的 j 索引和 i+1 索引之间的字符串是不是回文
if nums[j:i+1] == nums[j:i+1][::-1]:
a = nums[j:i+1]
# 首次满足的长度最大
break
# 判断当前回文的长度和已知的长度比较 大的话更新 max_len 和 num
if i+1 - j > max_len:
max_len = i+1 - j
num = a
else:
# 添加字符出现的索引
D[s] = [i]
print(num)
输出:’bab'
动态规划
nums = 'babad'
n = len(nums)
# 用 dp 矩阵记录nums子序列的状态
# 若 dp[i][j] = True,表示 nums[i:j+1] 为回文串
# dp[i][j] = False,表示 nums[i:j+1] 不是回文串
dp = [[False]*n for _ in range(n)]
# 由于单个字符均是回文串,所以设置dp[i][j]为True。且 j>=i ,即dp的下三角全是不能用的
for i in range(n):
dp[i][i] = True
max_len = 1 # 初始化最大长度
start = 0 # 初始化最长回文串的起始位置
# 已经设置对角线上的状态全为 True,这里从索引 1 开始
for j in range(1, n):
# 满足 j > i
for i in range(j):
# 如果dp[i][j] <= 2,意味着nums[i:j+1]为回文串的前提是两端相等。
if j-i <= 2:
if nums[j] == nums[i]:
# 更新状态 和 计算当前长度
dp[i][j] = True
curent_len = j-i+1
else:
# 如果dp[i][j] > 2,意味着nums[i:j+1]为回文串的前提是两端相等 和 nums[i+1:j]也是回文串。
if nums[j] == nums[i] and dp[i+1][j-1]:
dp[i][j] = True
curent_len = j-i+1
# 如果是回文串,比较当前长度和之前长度的大小,变大更新最大长度和起始位置。
if dp[i][j]:
if curent_len > max_len:
max_len = curent_len
start = i
# 通过最大长度和起始索引计算回文串。
print(nums[start:start+max_len])
输出:’bab'