最长公共子序列

题目描述:给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。

说明:

最长公共子序列的定义:最长公共子序列问题是在一组序列(通常2个)中找到最长公共子序列(注意:不同于子串,LCS不需要是连续的子串)。该问题是典型的计算机科学问题,是文件差异比较程序的基础,在生物信息学中也有所应用。https://en.wikipedia.org/wiki/Longest_common_subsequence_problem


样例:

给出"ABCD" 和 "EDCA",这个LCS是 "A" (或 D或C),返回1

给出 "ABCD" 和 "EACB",这个LCS是"AC"返回 2


什么是LCS,上面的定义已经很清楚了。我不赘述了。我们之前做的一道题是求两个字符串之间的不同的子序列(详见:点击打开链接),本题也是关于子序列的,所以两道题肯定有类似的地方。我们还是用动态规划(其实你见的多了就会立马有种感觉,知道这道题该用动态规划),用二维表格record[i][j]表示字符串A的前 i 项与字符串B的前 j 项的LCS的长度。

现在开始写状态转移方程。我们来分析A[i]与B[j]的关系对两个串的LCS的长度造成的影响。

1. 若A[i] == B[j],那么,很显然,A的前 i 项与B的前 j 项的LCS为A的前 i - 1项与B的前 j - 1项的LCS加上A[i]。比如,A = "bupt", B= "bupat"中,最后一项相同,除最后一项外,前面的项为A' = "bup", B' = "bupa",A'与B'的LCS为“bup”,所以A与B的LCS为“bup” + "t"

2. 若A[i] != B[j],这时候的情况就会比较复杂:

(1)若A[i]与B[j]谁都没有为A的前 i 项与B的前 j 项的LCS做出“贡献”,那A的前 i 项与B的前 j 项的LCS为A的前 i - 1项与B的前 j - 1项的LCS是一样的。比如,A = "bupta" 与 B = "bupec"的LCS还是A' = "bupt", B' = "bupe"的LCS

(2)若A[i]与B[j]有一个A的前 i 项与B的前 j 项的LCS做出“贡献”,A的前 i 项与B的前 j 项的LCS则必然与

<1>. A的前 i - 1项与B的前 j 项的LCS

<2>. A的前 i 项与B的前 j - 1项的LCS

有一个是相同的。比如,A = "bupte" 与 B = "bupec",A的最后一项"e"为A, B的LCS做出“贡献”了,那么LCS为A = "bupte" 与 B‘ = "bupe"的LCS是相同的,且长度一定大于A' = "bupt"与B = "bupec"的LCS。


因此,状态转移方程:

record[i][j] = record[i - 1][j - 1] + 1(A[i] == B[j])

record[i][j] = max(record[i - 1][j], record[i][j - 1])

初始条件与求两个字符串之间的不同的子序列的设定是类似的,都是先拓展这个二维表格,使得行,列各增加一个,这也是动态规划常用的方法,我就不多了,不理解的话返回上面给出的链接自己学习。


代码如下:

class Solution:
    """
    @param A, B: Two strings.
    @return: The length of longest common subsequence of A and B.
    """
    def longestCommonSubsequence(self, A, B):
        m = len(A)
        n = len(B)
        if m == 0 or n == 0:
            return 0
        record = [[0 for j in range(n + 1)] for i in range(m + 1)]
        i = 1
        while i <= m:
            j = 1
            while j <= n:
                if A[i - 1] == B[j - 1]:
                    record[i][j] = record[i - 1][j - 1] + 1
                else:
                    record[i][j] = max(record[i - 1][j], record[i][j - 1])
                j += 1
            i += 1
        return record[m][n]
        # write your code here

需要注意的是,LCS在数据挖掘中很很有用的方法,正如题目所描述的那样。我在以后会对判断两个文件的相似度做一个专题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值