算法实践9-1 LCS
问题:
给定序列\(a\)和\(b\),求它们的最长公共子序列。
解析
设\(dp[i][j]\)为在\(a\)串的前\(i\)个字符和\(b\)串的前\(j\)个字符中找到的\(LCS\)。我们枚举\(i\)和\(j\),当\(a[i] == b[j]\)时,我们让\(i\)和\(j\)配对的结果一定时最优的。如果我们此时不选择配对,那么就只能选择让\(i\)或者\(j\)失配,选择\(dp[i - 1][j]\)或者\(dp[i][j - 1]\)的答案。但失配的\(i\)或者\(j\)对于答案的最大贡献就是\(1\),所以产生的最多贡献是一样的。如果不相等,就直接在适配的里面取大即可。
设计
for (int i = 1; i <= lena; ++i) {
for (int j = 1; j <= lenb; ++j) {
if (a[i] == b[j]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
}
}
}
分析
遍历字符串\(a\),\(b\),时间复杂度\(O(n^2)\)
源码
https://github.com/Sstee1XD/Algorithm_homework/tree/main/实验9-1 LCS
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
const int inf = 0x3f3f3f3f;
const int N = 1e3 + 7;
int dp[N][N];
char a[N], b[N];
void solve() {
scanf("%s %s", a + 1, b + 1);
int lena = strlen(a + 1), lenb = strlen(b + 1);
for (int i = 0; i <= lena; ++i) dp[i][0] = 0;
for (int j = 0; j <= lenb; ++j) dp[0][j] = 0;
for (int i = 1; i <= lena; ++i) {
for (int j = 1; j <= lenb; ++j) {
if (a[i] == b[j]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
}
}
}
printf("%d\n", dp[lena][lenb]);
}
int main() {
// scanf("%d", &t);
int t = 1;
while (t--) solve();
return 0;
}
/*
abcfbc abfcab
*/

浙公网安备 33010602011771号