AcWing 897. 最长公共子序列
原题链接
简单
作者:
rushhhhh
,
2021-02-19 14:45:09
,
所有人可见
,
阅读 324
#include <iostream>
using namespace std;
/*
状态表示f[i,j]
集合:序列a的前i子序列和序列b的前j子序列的公共子序列
属性:子序列的长度,最大值
状态计算
00:不包含a[i]、b[j]
01:不包含a[i],包含b[j]
10:不包含b[j],包含a[i]
11:同时包含a[i]、b[j]
所以,对应情况如下:
f[i-1,j-1], f[i-1,j], f[i,j-1], f[i-1,j-1]+1
注意:
f[i-1,j]这个集合包含的公共子序列不一定包含b[j]
但是f[i-1,j]这个集合一定包含f[i-1,j-1](是它的子集)
所以,max包含f[i-1,j]了就可以不包含f[i-1,j-1](不同于f[i-1,j-1]+1)
f[i-1,j] 和 f[i-1,j-1]+1 是两个完全不同的集合!不知道两者的包含关系
总之,00、01、10、11四个状态的集合是由重叠的
而问题求的是最大值,所以集合有重叠也不影响结果(如果是数量则不行)
*/
const int N = 1010;
int n, m;
char a[N], b[N];
int f[N][N];
int main()
{
cin >> n >> m;
// 因为要用到i-1,所以往后错一位
cin >> a+1 >> b+1;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
f[i][j] = max(f[i-1][j], f[i][j-1]);
if(a[i] == b[j])
f[i][j] = max(f[i][j], f[i-1][j-1]+1);
}
cout << f[n][m];
return 0;
}