python实现最长公共子序列动态规划问题

用python写了一个用动态规划方法求两个序列的最长公共子序列,代码哪里有问题请指点。

# -*- coding: utf-8 -*-
# author:Huangyuliang
# 最长公共子序列问题
# 求 a,b 序列的最长公共子序列
import numpy as np

def lcs_len(a,b):
    n = len(a)
    m = len(b)
    p = n+1
    q = m+1
    c = np.zeros((p,q))
    val = c.copy()
    for i in range(1,p):
        for j in range(1,q):
            if a[i-1] == b[j-1]:
                c[i,j] = c[i-1,j-1] + 1
                val[i,j] = 0   # 在左上角
            elif c[i-1,j] >= c[i,j-1]:
                c[i,j] = c[i-1,j]
                val[i,j] = 1   # 在上方
            else:
                c[i,j] = c[i,j-1]
                val[i,j] = 2   # 在左方
    k = int(c[n,m])  # k 等于 最长公共子序列的元素个数
    print "k =",k
    G = range(k+1)   # G 用来保存最长公共子序列
    while k>0:
        if val[n,m]==1:
            n-=1
        elif val[n,m]==2:
            m-=1
        else:
            G[k] = a[n-1]
            k-=1
            n-=1
            m-=1
    return G[1:]

a,b = [1,2,3,5,7,8,9],[1,2,3,4,5,9]
h = lcs_len(a,b)
print h
输出结果:
k = 5
h = [1,2,3,5,9]
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最长公共子序列问题是一种经典的动态规划问题,在此为您提供 Python 代码实现: ```python def lcs(str1, str2): m = len(str1) n = len(str2) # 创建一个 m+1 行,n+1列的二维数组,用于保存子问题的最优解 dp = [[0] * (n+1) for _ in range(m+1)] # 计算子问题的最优解 for i in range(1, m+1): for j in range(1, n+1): if str1[i-1] == str2[j-1]: dp[i][j] = dp[i-1][j-1] + 1 else: dp[i][j] = max(dp[i-1][j], dp[i][j-1]) # 返回最长公共子序列的长度以及最长公共子序列本身 return dp[m][n], get_lcs(dp, str1, str2) def get_lcs(dp, str1, str2): i, j = len(str1), len(str2) lcs_str = '' while i > 0 and j > 0: if str1[i-1] == str2[j-1]: lcs_str = str1[i-1] + lcs_str i -= 1 j -= 1 elif dp[i-1][j] >= dp[i][j-1]: i -= 1 else: j -= 1 return lcs_str ``` 这个代码中,我们首先创建一个二维数组 dp 来保存子问题的最优解。然后,我们使用两个嵌套的循环遍历 str1 和 str2 中的每个字符,并计算子问题的最优解。最后,我们返回最长公共子序列的长度以及最长公共子序列本身。 在计算子问题的最优解时,我们会根据当前字符是否相等来进行判断。如果相等,那么最长公共子序列的长度应该加上 1,同时我们需要继续考虑 str1 和 str2 中下一个字符的匹配。如果不相等,我们就需要在 str1 和 str2 中分别跳过一个字符,然后继续考虑下一个字符的匹配。 最后,我们使用一个 while 循环来重建最长公共子序列。我们从 dp[m][n] 开始,一步步往回找到最长公共子序列的每个字符,并将它们添加到 lcs_str 中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值