导读 ^ _ ^
子序问题可以说是最常见的DP问题。
接着上期内容,接着讲子序问题中的经典问题
这期讲解最长公共子序列问题。
最长公共子序列
本题leetcode有相关链接,但是为了防止依赖于核心代码模式。我们先自己尝试用acm模式进行思考写代码。后文也给出了C++的leetcode代码。
思路
代码实现
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int n,m;
char a[N],b[N];
int f[N][N];
int main( ) {
scanf("%d%d",&n,&m);
scanf("%s%s",a+1,b+1);//下标1开始输入
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
f[i][j] = max(f[i - 1][j], f[i][j - 1]);
if(a[i] == b[j]) f[i][j] = max(f[i][j], f[i-1][j-1] + 1);
}
printf("%d",f[n][m]);
return 0;
}
leetcode题目
leetcode 1143
代码与思路
确定状态
- dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]
- text1[i - 1] 与 text2[j - 1]相同,text1[i - 1] 与 text2[j - 1]不相同
- text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;
- text1[i - 1] 与 text2[j - 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));
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]);
}
}
}
return dp[text1.size()][text2.size()];
}
};