洛谷 P1439 【模板】最长公共子序列 菜鸟题解

有志者,事竟成,破釜沉舟,百二秦关终属楚。
苦心人,天不负,卧薪尝胆,三千越甲可吞吴。

P1439 【模板】最长公共子序列

题目链接:

https://www.luogu.com.cn/problem/P1439

在这里插入图片描述

题目解释:

没什么好解释的,看看时间复杂度, n l o g n nlog_n nlogn求正解,所以简单的DP是不行的,换思路。

问题分析:

这个题应该有很多解,很多博主写过了,主要解法就是用最长上升子序列,至于为什么用最长上升子序列解最长公共子序列,我今天主要解释一下这个问题。

首先看样例:给的数据是:

5
3 2 1 5 4
1 2 3 4 5

首先明确题目中说了,整个序列是1~n的全排列,所以不会出现重复的数字。

题目思路:

1、

先明确一点,两个串的最长公共子序列一定是第一个串的子串,及相对位置一定不变。

2.

先新建一个ind[]数组,用来存储每个数字出现的位置是什么,对于输入的第一个序列,ind[] = {3, 2, 1, 5, 4};这个数组的意思是数字1在第3个出现,数字2在第2个出现,数字3在第1个出现,数字4在第5个出现,数字5在第4个出现。对于ind[]和第一个数组相同,这个是因为测试样例的偶然,并不是因为所有的。

3、

之后在第二个序列中,也就是1 2 3 4 5,用第一个中得到的ind[]位置数组替换第二个数组中的数字,得到3 2 1 5 4。

替换之后的整个数组代表的什么意思,就是第二个序列以第一个序列为基准的的下标值,只要保证这个下标值出现的序列是上升的,就能保证这个转化后的第二个序列在第一个序列中是顺序出现的.

至此整个问题已经转化成了最长上升子序列问题。然后就是最长上升子序列 n l o g n n log_n nlogn的板子。

AC代码:

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

const int N = 1e5 + 7;
int a[N], b[N];
int dp[N] = {0};

int main(){
    int n;
    ios::sync_with_stdio(false);
    cin >> n;
    int tmp = 0;
    for (int i = 1; i <= n; i++){
        cin >> tmp;
        a[tmp] = i;
    }
    for (int i = 1; i <= n; i++){
        cin >> tmp;
        b[i] = a[tmp];
    }
    int len = 1;
    dp[1] = b[1];
    for (int i = 2; i <= n; i++){
        if (dp[len] < b[i]) dp[++len] = b[i];
        else{
            int p = upper_bound(dp + 1, dp + 1 + len, b[i]) - dp;
            dp[p] = b[i];
        }
    }
    cout << len << endl;
    return 0;
}

板子还是要背下来的,尤其是时间复杂度低的板子。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值