
复杂度 \(O(n \cdot m)\)
总体复杂度 $ 1000 \times 1000 = 1 \times 10^{6} $
点击查看代码
#include<iostream>
using namespace std;
const int N = 1010;
int n, m;
char a[N], b[N];
int f[N][N];
int main()
{
cin >> n >> m >> 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] << endl;
return 0;
}
- 状态表示
$ f[i][j] $ 表示所有在第一个序列的前 \(i\) 个字母中出现,并且在第二个序列的前 \(j\) 个字母中出现的子序列
- 状态转移
$ f[i][j] $ 可以分成四种情况:
① 不选 \(a[i]\) 和 \(b[j]\) ,等价于 \(f[i - 1][j - 1]\)
② 选 \(a[i]\) 和 \(b[j]\) ,如果 \(a[i] = b[j]\) ,等价于 \(f[i - 1][j - 1] + 1\)
③ 选 \(a[i]\) ,不选 \(b[j]\) ,包含于 \(f[i][j - 1]\)
③ 不选 \(a[i]\) ,选 \(b[j]\) ,包含于 \(f[i - 1][j]\)
取四种情况的最大值,而 $ f[i - 1][j - 1] $ 包含于 $ f[i][j - 1] $ 和 \(f[i - 1][j]\) ,故只需取三种情况的最大值
\(f[i][j] = max(f[i][j - 1], f[i - 1][j], f[i - 1][j - 1] + 1)\)
- 也可以这样分类:
① 选 \(a[i]\) 和 \(b[j]\) ,如果 \(a[i] = b[j]\) ,等价于 \(f[i - 1][j - 1] + 1\)
② 不选 \(a[i]\) ,等价于 \(f[i - 1][j]\)
③ 不选 \(b[j]\) ,等价于 \(f[i][j - 1]\)