算法实践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
*/
posted @ 2021-06-22 22:29  stff577  阅读(40)  评论(0)    收藏  举报