P1439 【模板】最长公共子序列
题意
给定 的两个排列 、,求它们的最长公共子序列(LCS)长度。
思路
经典做法是 动态规划,但对于 的数据会超时。利用“两个序列都是排列”的性质,可以将 LCS 转化为 LIS(最长上升子序列):
- 建立哈希(或数组)
mp[val] 记录值 val 在序列 中的位置;
- 遍历 ,将 $P_2[i]
在 $P_1$ 中的位置mp[P2[i]]` 依次写入新数组;
- 问题就变成了:求该新数组的 LIS 长度,使用
lower_bound + 贪心即可达到 。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include <bits/stdc++.h> using namespace std;
const int N = 100000 + 5; int pos[N], b[N];
int main() { ios::sync_with_stdio(false); cin.tie(nullptr);
int n; cin >> n; for (int i = 1; i <= n; ++i) { int v; cin >> v; pos[v] = i; } for (int i = 1; i <= n; ++i) cin >> b[i];
vector<int> lis; lis.reserve(n); for (int i = 1; i <= n; ++i) { int mapped = pos[b[i]]; auto it = lower_bound(lis.begin(), lis.end(), mapped); if (it == lis.end()) lis.push_back(mapped); else *it = mapped; } cout << lis.size() << '\n'; return 0; }
|