二者区别:一个要求连续,一个可以不连续
- dp[i][j]:以下标i-1结尾的A和下标
j-1
结尾的B,最长重复子数组长度为dp[i][j]
- 递推公式:当
A[i - 1] == B[j - 1]
,dp[i][j] = dp[i-1][j-1] + 1
,故i和j得从1开始遍历。- 初始化
由dp[i]数组的含义可知,dp[i][0]和dp[0][j]都是没有意义的,但dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;
所以dp[i][0] 和dp[0][j]初始化为0。- 确定递推顺序
外层for遍历A,内层for遍历B- 举例推导dp数组
class Solution {
public:
int findLength(vector<int>& nums1, vector<int>& nums2) {
vector<vector<int> > dp(nums1.size() + 1, vector<int>(nums2.size() + 1, 0));
for(int i = 0; i < nums1.size(); i++)
dp[i][0] = 0;
for(int i = 0; i < nums2.size(); i++)
dp[0][i] = 0;
int res = 0;
for(int i = 1; i <= nums1.size(); i++){
for(int j = 1; j <= nums2.size(); j++){
if(nums1[i-1] == nums2[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
}
if(dp[i][j] > res) res = dp[i][j];
}
}
return res;
}
};
滚动数组
class Solution {
public:
int findLength(vector<int>& nums1, vector<int>& nums2) {
//vector<vector<int> > dp(nums1.size() + 1, vector<int>(nums2.size() + 1, 0));
vector<int> dp(nums2.size() + 1, 0);
//for(int i = 0; i < nums1.size(); i++)
//dp[i][0] = 0;
// for(int i = 0; i < nums2.size(); i++)
// dp[0][i] = 0;
int res = 0;
for(int i = 1; i <= nums1.size(); i++){
for(int j = nums2.size(); j >= 1; j--){
if(nums1[i-1] == nums2[j-1]){
dp[j] = dp[j-1] + 1;
}else dp[j] = 0; //!!!置为0
if(dp[j] > res) res = dp[j];
}
}
return res;
}
};
与上一题的区别就是不要求连续,但是相对顺序不能变
dp[i][j]
表示以i-1
结尾的A数组和j-1
结尾的B数组之间的最长公共子序列的长度- 递推公式:若
text1[i-1] == text2[i-1]
,则有dp[i][j] = dp[i-1][j-1] + 1
;否则话dp[i][j] = max(dp[i-1][j], dp[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));
int res = 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-1][j], dp[i][j-1]);
if(dp[i][j] > res) res = dp[i][j];
}
}
return res;
}
};
这题与最长公共子序列很像,只是说t是可以跳跃元素的,而s不能
故当s[i-1] != t[j-1])
时,dp[i][j] = dp[i][j-1]
。(注意不是dp[i][j] = max(dp[i][j-1], dp[i-1][j])
)
class Solution {
public:
//用最长重复子序列去求解
bool isSubsequence(string s, string t) {
vector<vector<int> > dp(s.size()+1,
vector<int>(t.size()+1, 0));
int maxLen = INT_MIN;
for(int i = 1; i <=s.size(); i++){
for(int j = 1; j <= t.size(); j++){
if(s[i-1] == t[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
}
else dp[i][j] = dp[i][j-1];
}
}
return dp[s.size()][t.size()] == s.size();
}
};
用双指针
class Solution {
public:
bool isSubsequence(string s, string t) {
int i = 0, j = 0;
int res = 0;
while(i < s.size() && j < t.size()){
if(s[i] == t[j]){
i++;
res++;
}
j++;
}
return res == s.size();
}
};