--- title: "最长公共上升子序列" created: 2025-11-28 tags: - 算法 --- # 最长公共上升子序列 ## 题目 [最长公共上升子序列](https://www.acwing.com/problem/content/description/274/) ![[image-e975ff7a.png]] ## 思路分析 这是两个**经典DP模型**的结合版: LIS(最长上升子序列,Longest Increasing Subsequence) `for(j=1;j using namespace std; const int N=3010; int a[N],b[N]; int f[N][N]; int n; int main() { 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++){ for(int j=1;j<=n;j++){ f[i][j]=f[i-1][j]; if(a[i]==b[j]){ for(int k=0;kb[k]){ f[i][j]=max(f[i][j],f[i-1][k]+1); } } } } } int res=0; for(int i=0;i<=n;i++) res=max(res,f[n][i]); cout<b\_k$ 每次用到的 状态 都是第 i - 1 个阶段的 因此我们可以用一个变量,存储上一个阶段的能够接在 a[i] 前面的最大的状态值 ## 代码实现 ```cpp #include using namespace std; const int N = 3010; int n; int a[N], b[N]; int f[N][N]; int main() { 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; for (int j = 1; j <= n; ++ j) { f[i][j] = f[i - 1][j]; if (b[j] == a[i]) f[i][j] = max(f[i][j], maxv); if (b[j] < a[i]) 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; return 0; } ``` ## 同类题型 ## 视频讲解 --- ⬅️ [[最长上升子序列模型练习|最长上升子序列模型练习]] 🏠 [[00-刷题理模型]] ➡️ [[最长公共子序列|最长公共子序列]]