python找出字符串中的最长回文串子序列

回文串,即:

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'

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值