帕先生之最长公共子序列LeetCode 1143

46 阅读1分钟

1、 题目描述

给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度

2、 动态规划解题思路

参考上节最长公共子数组解题思路

1、我们可以定义dp数组以i-1与j-1号元素作为结尾的公共子序列的长度,公共子序列的结尾必须是i-1和j-1

2、递推公式:

如果text1[i1]==text2[j1]:dp[i][j]=dp[i1][j1]+1 如果text1[i-1] == text2[j-1]: dp[i][j] = dp[i-1][j-1] + 1
如果不等:dp[i][j]=max(dp[i1][j],dp[i][j1]) 如果不等: dp[i][j] = max(dp[i-1][j], dp[i][j-1])

3、初始化:

因为dp是以i-1j-1结尾来计算的, 所以dp[i][0] 表示的是text1[i-1]text2[0-1]的元素, 索引为负, 没有意义, 所以初始化为0, dp[0][j]也是同理, 其余值, 因为求长度, 所以默认全部初始化为0

dp[text1.length]代表的是text1[length-1]

遍历的时候这里的i < text1.length+1

4、 遍历顺序:

1.png

可以看到dp[i][j]是由i-1j-1推导而来, 所以ij都是从上往下, 从左到右的遍历顺序

同时ij都是从下标1开始, 因为dp数组的定义是i-1j-1

5、输出结果:每次计算dp数组的时候, 一起求下最值, 最后返回

3、代码实现

class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        result = 0
        dp = [ [ 0 for i in range(len(text2)+1)] for j in range(len(text1)+1)]
        for i in range(1, len(text1)+1):
            for j in range(1, len(text2)+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])
                result = max(result, dp[i][j])
        return result