动态规划之四:最长公共子序列

本文介绍如何求解两个序列的最长公共子序列(LCS)问题,给出了示例输入输出,并详细解释了基本概念和状态转移方程。通过动态规划优化算法,避免指数级复杂度,实现高效求解。
摘要由CSDN通过智能技术生成

问题:已知两个序列的长度分别为m、n,求取这两个序列的最长公共子序列LCS(longest common sequence)的长度?

示例描述:

    输入:

         第一行输入两个整数分别为n、m,它们分别代表序列source以及dest 的长度

         第二行输入序列source的值

         第三行输入序列dest的值

  输出:

        输出最长子序列的长度。

实例:

  输入:

       8 9

       1 3 4 5 6 7 7 8

       3 5 7 4 8 6 7 8 2

  输出:

       5

基本概念:

     子序列:将一个给定的序列的零个或多个元素丢掉之后得到的结果。

     子串:一个给定序列的任意连续元素组成的子序列。

下面使用图例进行概念说明:


在这一关中,我们将学习如何找到两个字符串的最长公共子序列最长公共子序列(LCS)指的是两个字符串中,所有公共子序列中最长的那个。例如,字符串“ABCD”和“ACDF”中的最长公共子序列为“ACD”。 我们可以使用动态规划来解决这个问题。我们可以创建一个二维数组dp,其中dp[i][j]表示字符串s1的前i个字符和字符串s2的前j个字符的最长公共子序列长度。 我们可以使用以下递推公式来填充整个数组: 如果s1[i-1] == s2[j-1],则dp[i][j] = dp[i-1][j-1] + 1,因为当前字符在两个字符串中都出现了,所以我们可以将它添加到最长公共子序列中。 如果s1[i-1] != s2[j-1],则dp[i][j] = max(dp[i-1][j], dp[i][j-1]),因为当前字符只能添加到s1或s2中的一个子序列中,所以我们需要找到哪个子序列的LCS更长,然后将当前字符添加到该子序列中。 最终,LCS的长度将存储在dp[m][n]中,其中m和n分别是s1和s2的长度。我们可以使用逆推法来找到LCS本身。我们从dp[m][n]开始,如果s1[i-1] == s2[j-1],则将该字符添加到LCS中,并向左上移动一个位置,否则我们将向左或向上移动一个位置。 下面是一个Python实现的示例代码: def longest_common_subsequence(s1, s2): m, n = len(s1), len(s2) dp = [[0] * (n+1) for _ in range(m+1)] for i in range(1, m+1): for j in range(1, n+1): if s1[i-1] == s2[j-1]: dp[i][j] = dp[i-1][j-1] + 1 else: dp[i][j] = max(dp[i-1][j], dp[i][j-1]) lcs_len = dp[m][n] lcs = "" i, j = m, n while i > 0 and j > 0: if s1[i-1] == s2[j-1]: lcs = s1[i-1] + lcs i -= 1 j -= 1 elif dp[i-1][j] > dp[i][j-1]: i -= 1 else: j -= 1 return lcs
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值