【Leetcode】1143.最长公共子序列
1143.最长公共子序列
题目
给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。
注:两个字符串的「公共子序列」(Longest Common Subsequence,简称 LCS)是这两个字符串所共同拥有的子序列。若这两个字符串没有公共子序列,则返回 0。
示例 1:
输入:text1 = "abcde", text2 = "ace"
输出:3
解释:最长公共子序列是 "ace",它的长度为 3。
示例 2:
输入:text1 = "abc", text2 = "abc"
输出:3
解释:最长公共子序列是 "abc",它的长度为 3。
示例 3:
输入:text1 = "abc", text2 = "def"
输出:0
解释:两个字符串没有公共子序列,返回 0。
方法(动态规划)
遇到子序列相关的问题,可以往动态规划上考虑。这道题让我们在两个字符串中寻找共同拥有的最长子序列,因此很容易想到用二维动态规划来解决。
1.定义dp数组
定义$dp[i][j]$为:$str1[0…i-1]和str2[0…j-1]$的最长公共子序列长度。
2.Base Case
根据上述dp数组的定义,可以写出如下Base Case:
- i为0时,str1[0…i-1]不构成一个字符串,因此不存在与str2的公共子序列,因此dp[0][j]为0
- j为0时,str2[0…j-1]不构成一个字符串,因此不存在于str1的公共子序列,因此dp[i][0]为0
3.状态转移方程
当str1遍历到i - 1,str2遍历到j - 1时,即要求$str1[0…i-1]和str2[0…j-1]$的最长公共子序列长度时,需要考虑以下的几种情况:
如果str1[i - 1]与str2[j - 1]相等,那么肯定要将其放入str1[0…i−1]和str2[0…j−1]的LCS当中,有了这个字符,LCS的长度就会加1,因此
$$dp[i][j] = dp[i - 1][j - 1] + 1$$如果str1[i - 1]与str2[j - 1]不等,则又会分为以下的三种情况:
str1[i - 1]与str2[j - 1]都不放入LCS当中,那么LCS的长度不会产生变化,即dp[i][j] = dp[i - 1][j - 1]
str1[i - 1]放入LCS中,但str2[j - 1]不放。这时dp[i][j] = dp[i][j - 1]
str1[i - 1]不放入LCS中,但str2[j - 1]放。这时dp[i][j] = dp[i - 1][j]
由于在dp[i][j]这个位置可以做上述三种选择,因此取三种选择可能产生的最大值,即为dp[i][j]。即:
$$dp[i][j] = max(dp[i - 1][j - 1],dp[i][j - 1],dp[i - 1][j])$$
代码
1 |
|
- 时间复杂度:O(m * n)
- 空间复杂度:O(m * n)
其中,m和n分别为str1和str2的长度