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.
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$. 最长公共子序列](https://www.acwing.com/problem/content/description/899/)
### 一、题目描述
给定两个长度分别为 $N$ 和 $M$ 的字符串 $A$ 和 $B$,求既是 $A$ 的子序列又是 $B$的子序列的字符串 ** 长度最长** 是多少。
** 输入格式**
第一行包含两个整数 $N$ 和 $M$。
第二行包含一个长度为 $N$ 的字符串,表示字符串 $A$。
第三行包含一个长度为 $M$ 的字符串,表示字符串 $B$。
字符串均由小写字母构成。
** 输出格式**
输出一个整数,表示最大长度。
** 数据范围**
$1≤N,M≤1000$
** 输入样例**:
```cpp {.line-numbers}
4 5
acbd
abedc
```
**输出样例**:
```cpp {.line-numbers}
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]$
* 如果两个都没有贡献,那么就是$f[i-1][j-1]$

### 三、实现代码
```cpp {.line-numbers}
#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;
}
```