题解:P1439 【模板】最长公共子序列
前置知识
- 最长上升子序列(及其二分求法);
- 最长公共子序列(LCS):两个序列中共同包含的最长子序列(可能有多个);
二分。
暴力求 LCS
可用
解释:如果当前的
由于我们要把两个序列的每一对
但是,这个算法不能通过这一题。(不过这题是可以的,只要稍作“魔改”就可以了。)
(特殊)优化
LCS 转化为 LIS
因为本题中保证
而公共子序列只要保证在两序列中的顺序一样。
所以,我们可以用一个映射数组(记为
时间复杂度即为求 LIS 的复杂度。如用二分求,为
二分求 LIS
本部分将简要介绍 LIS 的
令
而之后的
即
实现
(只给出输入和算法实现,不可直接编译)
struct N {
int data, id;
};
N a[MAXN], b[MAXN];
int m[MAXN], g[MAXN], n, ans = 0;
int main() {
cin >> n;
for(int i=1; i<=n; ++i){
cin >> a[i].data;
m[a[i].data] = i;
a[i].id = i;
}
for(int i=1; i<=n; ++i){
cin >> b[i].data;
b[i].id = i;
}
memset(g, 0x77, sizeof g);
g[1] = a[1];
for(int i=1; i<=n; ++i){
int x = m[b[i].data];
int pos = lower_bound(g+1, g+n+1, x) − g;
ans = max(ans, pos);
g[pos] = min(x, g[pos]);
}
cout << ans;
return 0;
}
最后
假如 DP 欺骗了你,不要悲伤,不要心急。\ 忧郁的日子里需要学习;相信吧,胜利终将属于你。