洛谷 P1439 【模板】最長公共子序列 題解
阿新 • • 發佈:2019-03-02
inf bubuko return https == span ++ 每一個 upper
題目傳送門
看起來是一道十分經典的LCS問題
很容易想到 n2 的一般算法:
主題代碼如下:
for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++){ dp[i][j] = max (dp[i-1][j], dp[i][j-1]); if (a[i] == b[j]) dp[i][j] = max (dp[i][j], dp[i-1][j-1] + 1); } printf ("%d", dp[n][n]);
但往下看一眼數據範圍 :
沒錯, n ≤100000 ,n²直接 TLE
題目描述中提到了兩組數都是 自然數1-n的一個排列
所以這題可以這麽來做:
設兩個數組分別為 a 和 b
對於每一個a數組中的數,一定有一個唯一對應的相等的b數組中的數
可以將a數組中的數看作 1,2,3,4,5......n
將b數組中的數也變為對應的值,假設變為數組c,可以發現,這變成了一個最長上升子序列LIS問題
當c中的數有一個上升子序列時,則這個序列在原數組中一定與a數組是公共的
模擬一遍樣例:
先把第一列數看作 1, 2, 3, 4, 5。 則3對應1, 2對應2, 1對應3 .......
第二列數變為 3, 2, 1, 4, 5
最長上升子序列為 1, 4, 5 或 2, 4, 5或3, 4, 5
可以發現,這三個序列在原數組中都能找到相應的公共部分
所以答案為3
完整代碼:
#include <bits/stdc++.h> using namespace std; #define f(i, r) for (int i = 1; i <= r; i++) int n, x, a[100005], k[100005], len, q[100005]; int main(){ scanf ("%d", &n); f (i, n) scanf ("%d", &x), k[x] = i; f (i, n) scanf ("%d", &a[i]), a[i] = k[a[i]]; f (i, n){ if (a[i] > q[len]) q[++len] = a[i]; else{ int w = upper_bound (q + 1, q + len + 1, a[i]) - q; q[w] = a[i]; } } printf ("%d", len); return 0; }
洛谷 P1439 【模板】最長公共子序列 題解