题目大意:

有两个序列,现在我们找到公共的子序列,使得这个子序列最长。

首先我们看一下假如这个序列是非连续的序列。

​https://www.nowcoder.com/questionTerminal/c996bbb77dd447d681ec6907ccfb488a​​ 非连续子序列

解题思路:

首先定义dp状态dp[i][j],表示我们可以从a序列长度为i的前缀和b序列中长度为j的前缀得到的最长子序列。根据转移:

dp[i][j] = 1 + dp[i-1][j-1]  if a[i] == b[j]

dp[i][j] = max(dp[i-1][j],dp[i][j-1]); if a[i] != b[j]

其实这关系是显然的,因为假如当前字符是一样的,那么我们贪心地拿取总是最优的。

我们得到转移方程:

class LCS {
public:

int findLCS(string A, int n, string B, int m) {
// write code here
string a,b;
vector<vector<int>> dp;
a=A;b=B;
dp.assign(n+1,vector<int>(m+1,0));
int ret = 0;
for(int j = 1;j<=m;j++){
dp[1][j] = (a[0] == b[j-1]) ? 1:0;
dp[1][j] = max(dp[1][j],dp[1][j-1]);
}

for(int i = 1;i<=n;i++){
dp[i][1] = (a[i-1] == b[0]) ?1:0;
dp[i][1] = max(dp[i][1],dp[i-1][1]);
}
for(int i =2;i<=n;i++)
for(int j = 2;j<=m;j++){
if(a[i-1] == b[j-1])dp[i][j] = 1+dp[i-1][j-1];
dp[i][j] = max(dp[i][j], max(dp[i-1][j],dp[i][j-1]));
ret = max(ret,dp[i][j]);
}
return dp[n][m];
}
};

针对连续子序列:

​https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray/​

dp[i][j]表示当前字符串a[i:]和b[j:]组成的最长的子序列,我们的dp表可以从后往前刷

dp[i][j] = 1 + dp[i+1][j+1] if a[i] == b[j]

dp[i][j] = 0 if a[i] != b[j]

注意结果不是返回dp[0][0]

class Solution {
public:
vector<vector<vector<int>>> dp;
vector<int> mva;
vector<int> mvb;

int findLength(vector<int>& A, vector<int>& B) {
vector<vector<int>> dp(A.size()+1,vector<int>(B.size()+1,0));
int ret = 0;
for(int i = A.size() - 1;i>=0;i--)
for(int j = B.size()-1;j>=0;j--){
if(A[i] == B[j])dp[i][j] = dp[i+1][j+1] + 1;
ret = max(ret,dp[i][j]);
}

return ret;

}
};