算法提高之最长公共上升子序列
-
核心思想:线性dp
- 最长上升子序列 + 最长公共子序列 融合
- 状态表示:f[i][j]表示考虑 a 中前 i 个数字,b 中前 j 个数字 ,且当前以 b[j] 结尾的子序列的方案数
- 状态转移:当前a[i] != b[j] , f[i][j] = f[i-1][j]
- 当前a[i] == b[j] , f[i][j] = max(f[i][j],f[i-1][k]+1) 其中**k为j左侧的b[k]<b[j]**的元素
-
#include <iostream> using namespace std; const int N = 3010; int n; int a[N], b[N]; int f[N][N]; int main() { //input cin >> n; for (int i = 1; i <= n; ++ i) cin >> a[i]; for (int i = 1; i <= n; ++ i) cin >> b[i]; for (int i = 1; i <= n; ++ i) { int maxv = 1; //用maxv存最大的f[i-1][k] for(int j=1;j<=n;j++) { f[i][j] = f[i-1][j]; if(a[i] == b[j]) f[i][j] = max(f[i][j] , maxv); if(a[i] > b[j]) maxv = max(maxv , f[i-1][j] + 1); } } int res = 0; for (int i = 0; i <= n; ++ i) res = max(res, f[n][i]); cout << res << endl; }
参考题解:https://www.acwing.com/solution/content/52304/