You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

##AcWing 897. 最长公共子序列

一、题目描述

给定两个长度分别为 NM 的字符串 AB,求既是 A 的子序列又是 B的子序列的字符串 长度最长 是多少。

输入格式 第一行包含两个整数 NM

第二行包含一个长度为 N 的字符串,表示字符串 A

第三行包含一个长度为 M 的字符串,表示字符串 B

字符串均由小写字母构成。

输出格式 输出一个整数,表示最大长度。

数据范围 1≤N,M≤1000

输入样例

4 5
acbd
abedc

输出样例

3

二、LCS问题分析

状态表示 定义f[i][j]a[]i结尾,b[]j结尾的最长公共子序列长度

说明:没有说a[i]或者b[j]一定要出现在最长公共子序列当中!这个最长公共子序列,可能是a[]b[]的一些前序组成的,a[i],b[j]也可能没有对结果产生贡献。

  • a[i]==b[j]时,看一下两个字符串的前序,发现在少了a[i],b[j]后,转化为子问题f[i-1][j-1],问题转化为$f[i][j]=f[i-1][j-1]+1$

  • a[i] \neq b[j]时:

    • 如果a[i]不产生贡献,那么把它干掉f[i-1][j]
    • 如果b[j]不产生贡献,那么把它干掉f[i][j-1]

三、实现代码

#include <bits/stdc++.h>

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

int main() {
    // 递推式出现f[i-1][j-1]如果i,j从0开始会出现负值所以下标从1开始
    cin >> n >> m >> a + 1 >> b + 1;
    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]);
        }
    printf("%d", f[n][m]);
    return 0;
}