题目描述
给定两个字符串 text1
和 text2
,返回这两个字符串的最长公共子序列的长度。如果不存在公共子序列,返回 0 。
一个字符串的子序列是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。
两个字符串的公共子序列是这两个字符串所共同拥有的子序列。
linkLeetCode-1143 公共最长子序列
思路
假设字符串text1
和text2
的长度分别为 length1
和 length2
,创建二维数组 dp[length1][length2]
,其中 dp[i][j]
表示 text1[0:i]
和 text2[0:j]
的最长公共子序列的长度。
考虑动态规划的边界情况:
-
当
i=0
时,text1[0:i]
为空,空字符串和任何字符串的最长公共子序列的长度都是0
,因此对任意0≤j≤n
,有dp[0][j]=0
-
当
j=0
时,text2[0:j]
为空,同理可得,对任意0≤i≤m
,有dp[i][0]=0
。
当i>0 且 j>0
时,考虑 dp[i][j]
的计算:
- 当
text1[i−1]=text2[j−1]
时,将这两个相同的字符称为公共字符,考虑text1[0:i−1]
和text2[0:j−1]
的最长公共子序列,再增加一个字符(即公共字符)即可得到text1[0:i] 和 text2[0:j]
的最长公共子序列,因此dp[i][j]=dp[i−1][j−1]+1
- 当
text1[i−1]≠text2[j−1]
时,考虑以下两项:
-
text1[0:i−1] 和 text2[0:j]
的最长公共子序列; -
text1[0:i] 和 text2[0:j−1]
的最长公共子序列。
要得到text[0:i]
和text2[0:j]
的最长公共子序列,取两项中较大值,故dp[i][j] = max(dp[i-1][j], dp[i][j-1])
C++代码
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int length_1 = text1.size(), length_2 = text2.size();
// dp[i][j] : text1[0:i] 和 text2[0:j]的公共最长子序列
vector<vector<int>> dp(length_1 + 1, vector<int>(length_2 + 1));
for (int i = 0; i <= length_1; i++) {
dp[i][0] = 0;
}
for (int i = 0; i <= length_2; i++) {
dp[0][i] = 0;
}
for (int i = 1; i <= length_1; i++) {
char c1 = text1.at(i-1);
for (int j = 1; j <= length_2; j++) {
char c2 = text2.at(j-1);
if (c1 == c2) {
dp[i][j] = dp[i-1][j-1] + 1;
}
else {
dp[i][j] = max(dp[i][j-1], dp[i-1][j]);
}
}
}
return dp[length_1][length_2];
}
};