專題訓練2-DP - B - 最長公共子序列
阿新 • • 發佈:2022-03-28
題意
給出1∼n 的兩個排列P1 和 P2,求它們的最長公共子序列。
輸入格式
第一行是一個數 n (1≤n≤10^5)。
接下來兩行,每行為 n 個數,為自然數1∼n 的一個排列。
輸出格式
一個數,即最長公共子序列的長度。
思路
一開始用樸素的LCS演算法(O(n²))來寫,發現數據範圍到1e5會超時,然後向大佬學習一種新思路:
將LCS問題轉換為求LIS問題,具體做法就是將第一個序列的順序定義為“升序”,再對第二個序列求最大升序子序列(實際上是第一個序列的子序列),此時求出的子序列就是兩個原序列的公共子序列。
程式碼
#include <iostream> #include <algorithm> using namespace std; const int N = 1e5 + 5; int n, len = 0, x; int a[N], ind[N], q[N]; int bound(int x) { int l = 1, r = len; while (l < r) { int mid = (l + r) >> 1; if (ind[q[mid]] > ind[x]) r = mid; else l = mid + 1; } return l; } int main() { cin >> n; for (int i = 1; i <= n; i ++ ) cin >> a[i]; for (int i = 1; i <= n; i ++ ) { cin >> x; ind[x] = i; } for (int i = 1; i <= n; i ++ ) { if (ind[a[i]] > ind[q[len]]) q[++ len] = a[i]; else q[bound(a[i])] = a[i]; } cout << len << endl; return 0; }