状态:查看转移方程后AC。
这道题是研一期间刷的题目,也就是算法导论中的例子,整体思路和昨天的题很像,区别在于转移方程。注意,也要知道怎么样可以把这个公共子序列给提取出来。代码如下:
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
//dp[i][j] text1 i-1 和 text2 j-1 中的最大子序列长度
int len1 = text1.size(), len2 = text2.size();
vector<vector<int>> dp(len1+1, vector<int>(len2+1, 0));
for(int i = 1; i <= len1; ++i){
for(int j = 1; j <= len2; ++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]);
}
}
}
return dp[len1][len2];
}
};
状态:查看思路后AC。
本题的关键就是将其转换为两数组的最长公共子序列问题,代码如下:
class Solution {
public:
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
// 本质是找两个数组的最长公共子序列
int len1 = nums1.size(), len2 = nums2.size();
vector<vector<int>> dp(len1+1, vector<int>(len2+1, 0));
for(int i = 1; i <= len1; ++i){
for(int j = 1; j <= len2; ++j){
if(nums1[i-1] == nums2[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[len1][len2];
}
};
状态:AC。
之前用过贪心思路,但是动态规划的思路更容易想到,注意对res的使用。代码如下:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int len = nums.size();
vector<int> dp(len, 0);
dp[0] = nums[0];
int res = nums[0];
for(int i = 1; i < len; ++i){
dp[i] = max(dp[i-1]+nums[i], nums[i]);
if(dp[i] > res){ res = dp[i]; }
}
return res;
}
};
公共子序列/子串的打印
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Solution{
public:
// 最长公共子串
string maxSubseq(string s1, string s2){
int len1 = s1.size(), len2 = s2.size();
vector<vector<int>> dp(len1+1, vector<int>(len2+1, 0));
int res = INT_MIN, index = -1;
for(int i = 1; i <= len1; ++i){
for(int j = 1; j <= len2; ++j){
if(s1[i-1] == s2[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = 0;
}
if(dp[i][j] > res){
res = dp[i][j];
index = i;
}
}
}
return s1.substr(index-res, res);
}
// 最长公共子序列
string maxComseq(string s1, string s2){
int len1 = s1.size(), len2 = s2.size();
vector<vector<int>> dp(len1+1, vector<int>(len2+1, 0));
for(int i = 1; i <= len1; ++i){
for(int j = 1; j <= len2; ++j){
if(s1[i-1] == s2[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
string res = "";
int i = len1, j = len2;
while(i != 0 && j != 0){
if(s1[i-1] == s2[j-1]){
res += s1[i-1];
i--;
j--;
}else if(dp[i-1][j] > dp[i][j-1]){
i--;
}else if(dp[i-1][j] <= dp[i][j-1]){
j--;
}
}
reverse(res.begin(), res.end());
return res;
}
};
int main()
{
string s1 = "helloworld", s2 = "sawsogrlsdfa";
Solution ans;
string res1 = ans.maxSubseq(s1, s2);
cout << res1 << endl;
string res2 = ans.maxComseq(s1, s2);
cout << res2 << endl;
return 0;
}