题目大意:给定两个序列,求他们的最长公共子序列,题目多测。
考虑到这道题的数据范围比较小,(Nleq100),所以我们采用(n^2)的朴素方法即可。你觉得我会告诉你我不会nlogn的做法吗?!
我们定义状态(f[i][j])表示第一个串枚举到第(i)位,第二个串枚举到第(j)位时的最长公共子序列长度。
考虑如何转移,我们分情况讨论:
-
当(a[i-1]==b[i-1])时,考虑更新公共元素,显然此时的(f[i][j]=f[i-1][j-1]+1)
-
否则,我们考虑继承,那么(f[i][j])就应取(f[i-1][j])和(f[i][j-1])中最大值。
由于我们转移的时候需要枚举串(a)和串(b)的长度,所以这个的复杂度是(O(n^2))的。
最后,注意你的输出格式……
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#define max(a, b) ((a) > (b) ? (a) : (b))
// 对,我觉得using namespace std慢,所以没写
int f[110][110], a[110], b[110];
int main() {
std::ios::sync_with_stdio(0); // 关闭cin的同步缓存流,加快速度
int n, m, cnt = 0;
while (std::cin >> n >> m && (n != 0 || m != 0)) {
for (int i = 0; i < n; i++) std::cin >> a[i];
for (int i = 0; i < m; i++) std::cin >> b[i];
memset(f, 0, sizeof(f));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (a[i - 1] == b[j - 1]) f[i][j] = f[i - 1][j - 1] + 1;
else f[i][j] = max(f[i - 1][j], f[i][j - 1]); //核心转移方程
}
printf("Twin Towers #%d
Number of Tiles : %d
", ++cnt, f[n][m]);
puts(""); // 注意输出格式……
}
return 0;
}
完结撒花(*๓´╰╯`๓)