力扣:1143.最长公共子序列(LCS)
1、题目(longest-common-subsequence, LCS)
给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。示例 1:
输入:text1 = “abcde”, text2 = “ace”
输出:3
解释:最长公共子序列是 “ace” ,它的长度为 3 。
示例 2:输入:text1 = “abc”, text2 = “abc”
输出:3
解释:最长公共子序列是 “abc” ,它的长度为 3 。
示例 3:输入:text1 = “abc”, text2 = “def”
输出:0
解释:两个字符串没有公共子序列,返回 0 。
2、解答
最长公共子序列,子序列两个字母不一定挨在一起,只要顺序正确就是子序列。
求两个最长公共子序列的长度,从头到尾遍历text1
和text1
,分析可知,在遍历过程中,只可能遇到以下两种情况:
- text1[i] == text2[j];
- text1[i] != text2[j];
所以定义dp数组dp[text1.size()+1] [text2.size()+1]
;
dp[i][j]
表示text1 的0…i的部分和text2 的0…j的部分的最长公共子序列的大小。
所以根据以上分析的两种情况可以写出递推公式:
-
当
text1[i] == text2[j]
时 :dp[i][j] = dp[i - 1][j - 1] + 1
(即i-1和j-1的最长公共子序列+1) -
当
text1[i] != text2[j]
时:dp[i][j] = max(dp[i - 1][j],dp[i][j - 1])
(即i-1和j的最长公共子序列 与 i和j-1的最长公共子序列中的最大值)
代码如下:
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
vector<vector<int>> dp(text1.size() + 1, vector<int>(text2.size() + 1, 0));
//初始条件 : 各个长度的子序列与0长度的子序列的最长公共子序列的最大长度为0
for(int i = 1; i <= text1.size(); i++){
for(int j = 1; j <= text2.size(); j++){
if(text1[i - 1] == text2[j - 1]){
dp[i][j] = dp[i - 1][j - 1] + 1;
}else{
dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
}
}
}
return dp[text1.size()][text2.size()];
}
};