#include <cstdio>
#include <iostream>
#include <algorithm>
#include "cstdio"
using namespace std;
/// 集合 : a的前i 个字母,b的前j个字母 中所有公共子序列
/// 属性: 长度最大值 max
/// 状态 转移: 00 01 10 11 , 代表 a的第i 个字母,b的第j个字母包含不包含在公共子序列中
/// 00: f[i-1][j-1] 01 10 不好表示 ,可以用 包含这两个的集合来算 ,因为 f[i][j] 包含 f[i-1][j] 包含 01 , 以此类推10 , 求 max 可以有重复 ,只要不漏掉状态就可以,因为多个重复取最大值 仍然不变
/// 且 00 的f[i-1][j-1] 也可以省略 ,因为 f[i-1][j-1] 包含在 f[i][j-1] 和 f[i-1][j] 当中
const int N=1010;
int n,m;
int f[N][N];
char s1[N],s2[N];
int main() {
cin >> n >> m;
scanf("%s%s",s1+1,s2+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(s1[i] == s2[j])
f[i][j] = max (f[i][j] , f[i-1][j-1]+1);
}
}
cout <<f[n][m]<< endl;
return 0;
}
// 64 位输出请用 printf("%lld")
两个子串
一般就是 在第一个序列的 前i 个字母中出现 ,且在第二个序列的前j 个字母中出现的子序列
状态转移:
a[i] 和 b[j]是否 包含在子序列当中?
00 01 11 11
其中: 00,代表a[i] b[j]都不包含在子序列当中 ,那么
这片划分的 状态就是 f[i-1][j-1]
01,代表 a[i]不包含在子序列当中 ,但 b[j] 一定包含在子序列中 ,但是 f[i-1][j]的意思是 在第一个序列的前i-1个字母中出现,且在第二个序列的前j个字母中出现的子序列的全集 中的最长子序列 , 也就是 f[i-1][j] 是包含 01这种情况的, 因为 f[i-1][j] ,b[j]不一定就包含在公共子序列中.
10情况与01类似:
图解表示:
11 ,只有当 a[i] == b[j] 时, 这种情况才参与到max比较
这种状态为 f[i-1][j-1] + 1;
00: 可以不用写 ,因为 f[i-1][j-1]包含在 f[i-1][j] 和 f[i][j-1] 当中,

京公网安备 11010502036488号