题解:洛谷 P1439 两个排列的最长公共子序列

【题目来源】

洛谷:P1439 两个排列的最长公共子序列 - 洛谷 (luogu.com.cn)

【题目描述】

给出 \(1,2,\dots,n\) 的两个排列 \(P_1\)\(P_2\) ,求它们的最长公共子序列。

【输入】

第一行是一个数 \(n\)

接下来两行,每行为 \(n\) 个数,为自然数 \(1,2,\dots,n\) 的一个排列。

【输出】

一个数,即最长公共子序列的长度。

【输入样例】

5 
3 2 1 4 5
1 2 3 4 5

【输出样例】

3

【解题思路】

image

【算法标签】

《洛谷 P1439 最长公共子序列》 #动态规划,dp# #二分#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

const int N = 100005;  // 定义最大数组长度

int n;                 // 数组长度
int a[N], b[N];        // 输入的两个数组
int m[N];              // 记录a数组中每个值对应的位置
set<int> dp;           // 使用set维护最长递增子序列
set<int>::iterator it; // set的迭代器

int main()
{
    // 输入数组长度
    cin >> n;
  
    // 输入数组a并记录每个数字的位置
    for (int i = 1; i <= n; i++) 
    {
        cin >> a[i];
        m[a[i]] = i;  // 记录数字a[i]在a数组中的位置
    }
  
    // 输入数组b
    for (int i = 1; i <= n; i++) 
    {
        cin >> b[i];
    }
  
    // 初始化dp集合,插入第一个元素在a中的位置
    dp.insert(m[b[1]]);
  
    // 处理数组b的剩余元素
    for (int i = 2; i <= n; i++) 
    {
        // 在dp中查找第一个不小于当前元素位置的元素
        it = dp.lower_bound(m[b[i]]);
      
        // 如果找到这样的元素,删除它(维护最小末尾元素)
        if (it != dp.end())
        {
            dp.erase(it);
        }
      
        // 插入当前元素的位置
        dp.insert(m[b[i]]);
    }
  
    // 输出最长递增子序列的长度
    cout << dp.size();
  
    return 0;
}

【运行结果】

5 
3 2 1 4 5
1 2 3 4 5
3
posted @ 2026-02-20 19:17  团爸讲算法  阅读(2)  评论(0)    收藏  举报