最长公共子序列

c++

最长公共子序列

/*
最长公共子序列
  问题描述:
    给定两个长度分别为 N 和 M 的字符串 A 和 B,求既是 A 的子序列又是 B 的子序列的字符串长度最长是多少。
    输入格式
        第一行包含两个整数 N 和 M。
        第二行包含一个长度为 N 的字符串,表示字符串 A。
        第三行包含一个长度为 M 的字符串,表示字符串 B。
        字符串均由小写字母构成。
    输出格式
        输出一个整数,表示最大长度。
    数据范围
        1≤N,M≤1000
  解决方法:
    f[i][j] 表示 A[1..i] 和 B[1..j] 最长公共子序列长度
    我们讨论一下 f[i][j] 可能的方案
        1. 最长公共子序列的方案中 a[i] 并没有用到 f[i-1][j]
        2. 最长公共子序列的方案中 b[j] 并没有用到 f[i][j-1]
        3. a[i] 和 b[j] 都用到,那么需要条件 a[i] = b[j], f[i-1][j-1] + 1
        同时,可以证明当 a[i] = b[j],使用 a[i]和 b[j] 的结果一定不差于 f[i-1][j] 和 f[i][j-1]
    因此:
        if (a[i] == b[j]) {
            f[i][j] = f[i - 1][j - 1] + 1;
        } else {
            f[i][j] = max(f[i - 1][j], f[i][j - 1]);
        }
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>

using namespace std;

const int N = 1010;
int f[N][N];
int n, m;
char a[N], b[N];

int solution_one() {
    // initiate
    memset(f, 0, sizeof f);
    
    // dp
    for (int i = 1; i <= n; i ++ ) {
        for (int j = 1; j <= m; j ++ ) {
            if (a[i] == b[j]) {
                f[i][j] = f[i - 1][j - 1] + 1;
            } else {
                f[i][j] = max(f[i - 1][j], f[i][j - 1]);
            }
        }
    }

    // res
    return f[n][m];
}

int main()
{
    scanf("%d%d", &n, &m);
    scanf("%s", a + 1);
    scanf("%s", b + 1);

    int res = solution_one();

    printf("%d\n", res);

    return 0;
}


posted @ 2022-07-04 19:27  lucky_light  阅读(41)  评论(0编辑  收藏  举报