动态规划:最长公共子串和最长公共子序列

Posted 我家大宝最可爱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划:最长公共子串和最长公共子序列相关的知识,希望对你有一定的参考价值。

最长公共子串

给定两个字符串,求出最长的相同的子串,例如给定子串asdfaswerasdfaswer,其中两个子串串中共有的最长子串就是asdfas这个字符串。
同样,这道题一看就是动态规划,我们首先列出状态转移方程,假设两个字符串分别以i,j为结尾的最长公共子串长度为dp[i][j],当A[i]==B[j]时,dp[i][j]=dp[i-1][j-1]+1,如果这两个字符不相等,也就是说以A[i],B[j]为结尾的这两个字符串就不是公共子串,此时dp[i][j]=0

asdfas
werasdfasw
s1 = input()
s2 = input()

n1 = len(s1)
n2 = len(s2)

dp = [[0 for _ in range(n2)] for _ in range(n1)]
max_len = 0
for i,x in enumerate(s1):
    for j,y in enumerate(s2):
        if x == y:
            if i == 0 or j == 0:
                dp[i][j] = 1
            else:
                dp[i][j] = dp[i-1][j-1] + 1
        if dp[i][j] > max_len:
            max_len = dp[i][j]
print(max_len)

最长公共子序列

公共子序列不需要连续,因此,即使两个字符串不相等,dp[i][j]也不会为0。当前两个字符不等,t1[i]!=t2[j]的话,那么长度最少也是dp[i-1][j-1],但这还不够,因为我们希望拿到之前的比较中尽可能大的长度。那么当前字符已经不相等的情况下,就应该把当前的字符也放入到之前的比较中,那么一定有dp[i][j-1]和dp[i-1][j]>=dp[i][j]。简单来说,dp[i][j]的值应该从dp[i-1][j-1],dp[i][j-1],dp[i-1][j]三者中取,但dp[i][j]≤另外两个,故比较另外两个,取较大的。

我们定义的状态表示f数组和text数组下标均是从1开始的,而题目给出的text数组下标是从0开始的,为了一 一对应,在判断text1和text2数组的最后一位是否相等时,往前错一位,即使用text1[i - 1]和text2[j - 1]来判断。

这里解释一下为什么f数组和text数组均定义成下标从1开始。原因是因为状态转移方程 f[i][j] = max(f[i - 1][j],f[i][j - 1]), 当我们的f数组定义成下标从1开始以后,我们就可以在代码中不用对下标越界问题做出额外判断。其实我们也可以发现一个问题,就是题目给定的原数组,比如text数组,如果下标从1开始的话,状态表示会更加的清晰,推导状态转移方程的过程也会更加好理解。

class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        m, n = len(text1), len(text2)
        dp = [[0] * (n + 1) for _ in range(m + 1)]
        
        for i in range(1, m + 1):
            for j in range(1, n + 1):
                if text1[i - 1] == text2[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]
开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系

以上是关于动态规划:最长公共子串和最长公共子序列的主要内容,如果未能解决你的问题,请参考以下文章

最长公共子串和最长公共子序列(LCS问题)

最长公共子串和最长公共子序列(LCS问题)

动态规划——最长公共子序列

动态规划——最长公共子序列

动态规划——最长公共子序列与最长公共子串 (含Python实现代码)

最长公共子串和最长公共子序列