洛谷 P1439 【模板】最长公共子序列【线性dp+dp模型转换】

原题链接:https://www.luogu.com.cn/problem/P1439

题目描述

给出 1,2,…,n 的两个排列 P1​ 和 P2​ ,求它们的最长公共子序列。

输入格式

第一行是一个数 n。

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

输出格式

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

输入输出样例

输入 #1

5 
3 2 1 4 5
1 2 3 4 5

输出 #1

3

说明/提示

  • 对于 50% 的数据, n≤1e3;
  • 对于 100% 的数据, n≤1e5。

解题思路:

首先一看题目,我去这不是经典dp模型最长公共子序列吗,这也太简单了,本来准备直接上最长公共子序列的模板秒了,但是一看数据范围,n=1e5,最长公共子序列模板题的时间复杂度为O(n^2),这里的n=1e5,时间复杂度就到达了1e10,这也太高了,这个时间复杂度肯定过不了,这个时候肯定是观察状态转移方程根据状态转移方程看能不能进行优化,一看状态转移方程好像找不到什么好的优化方式,这个优化方式不存在,我们再看是否能够挖掘什么性质进行优化,我们可以发现a,b数组都是一个1-n的一个排列,也就是说俩个数组中都是1-n中的每个数只出现一次,下面让我们来画一个图模拟一下题目给出的样例,看看是否具有什么性质。

(1):首先我们知道公共子序列是每个位置都对应相等的,例如上述图中描述的样例,如果我们选择3,那么第一个序列的3和第二个序列的3就都要选上,那么此时就无法选择1和2,因为如果还选择1,那么第一个序列中选出的就是[3,1],第二个序列中选出的就是[1,3],这样俩个序列都不相同的了,肯定是不行的,然后如果选择2第一个序列就是[3,2],第二个序列就是[2,3]了,这也肯定是不行的,但是我们选择1之后是可以选择4和5的,这个时候我们就可以发现一个明显的性质了,这个性质就是我们将俩个数组a和b数值相等的位置连线之后,我们选择的公共子序列的所有数值对的连线不能不能存在交叉的现象。

(2):那么我们怎么保证我们选择的所有数值对的连线不交叉呢,我们可以根据数组a各个元素的相对位置来进行对应映射对数组b进行重新赋值,例如上述图中样例,在数组a中3位于第一个位置,所以将b数组中的3重新赋值为1 ,数组a中2位置第二个位置,所以将b数组中的2重新赋值为2,其他的也是如下赋值即可,这样原来的数组b为[1,2,3,4,5],就转换为了[3,2,1,4,5],对于映射之后重新赋值的新数组b,选择了某个位置之后,就不能选择b之前比当前选择位置大的数,不能选择b之后比当前位置小的数,例如这个新b数组选择了1之后,就不能选择1之前的2,3,但是可以选择1之后的4,5,看到这个这不就是求最长上升子序列吗,这个时候我们就将题目原本的求最长公共子序列变为了求新的b数组最长上升子序列,这个题目n=1e5,不能采用最长上升子序列的朴素dp写法,因为最长上升子序列的朴素dp写法时间复杂度为O(n^2),这个复杂度过不了,应该采用最长上升子序列的二分+贪心的那个写法,这种写法时间复杂度为O(nlogn),这个时间复杂度是可以过的。

时间复杂度:将原本求最长公共子序列转换为求映射的新数组b的最长上升子序列,使用求最长上升子序列的二分+贪心写法时间复杂度为O(nlogn)

总结:这个题目属于诈骗题了,题目表面是求最长公共子序列,但是n非常大,n=1e5,显然最长公共子序列的那个O(n^2)解法过不了,观察状态转移方程也没有发现很明显的优化方式,但是我们画图之后发现了一个性质,就将原本的求最长公共子序列变为了求最长上升子序列,然后采用最长上升子序列二分+贪心写法这个题目就可以过了,这个题目纯属套着羊皮的狼,挂羊头卖狗肉,题目给的虽然是求最长公共子序列,但是本质上就是求最长上升子序列。

启发:

至于我为什么能发现这个性质是因为我做一个非常像的题,所以很快就发现了这个性质,很快就解决了这个题目,所以说还是需要学会知识的迁移吧,对于学到的东西多加总结融会贯通还是有好处的,这样对于学过的东西,以后遇到类似的题目还是有帮助的。

那个很像的题目的链接:https://www.acwing.com/problem/content/1014/

cpp代码如下

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int N = 1e5 + 10;

int n;
int a[N], b[N], f[N];
int q[N];
int main()
{
    cin >> n;
    unordered_map<int, int> mp;
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]), mp[a[i]] = i;
    for (int i = 1; i <= n; i++)
        scanf("%d", &b[i]), b[i] = mp[b[i]]; // 根据a数组对b数组重新赋值,映射出一个新的b数组

    // 对于新映射出的b数组求最长上升子序列,这里是最长上升子序列的二分+贪心的写法,时间复杂度O(nlogn)
    int len = 0;
    for (int i = 1; i <= n; i++)
    {
        int l = 0, r = len;
        while (l < r)
        {
            int mid = l + r + 1 >> 1;
            if (q[mid] < b[i])
                l = mid;
            else
                r = mid - 1;
        }
        len = max(len, r + 1);
        q[r + 1] = b[i];
    }
    // len记录的就是新b数组的最长上升子序列
    cout << len << endl;
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/320174.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1359 · 有序数组转换为二叉搜索树

链接&#xff1a;LintCode 炼码 - ChatGPT&#xff01;更高效的学习体验&#xff01; 题解&#xff1a; ### 解题思路 1.每次随机一个要插入的数字&#xff08;避免搜索树过度不平衡&#xff09; 2.插入过的数字&#xff0c;就不在插入了 3.调用Insert1函数进行插入二叉搜索树…

TypeScript进阶(四)声明文件

✨ 专栏介绍 TypeScript是一种由微软开发的开源编程语言&#xff0c;它是JavaScript的超集&#xff0c;意味着任何有效的JavaScript代码都是有效的TypeScript代码。TypeScript通过添加静态类型和其他特性来增强JavaScript&#xff0c;使其更适合大型项目和团队开发。 在TypeS…

AI副业拆解:随心所欲地替换任何内容

在瞬息万变的世界里&#xff0c;保持“物体ID”的核心特质&#xff0c;同时创造无限可能的新内容&#xff0c;这是一场市场需求与技术挑战的双重交响。此刻&#xff0c;为您揭开一款颠覆性创新产品——ReplaceAnything框架。 直击痛点&#xff0c;破茧成蝶&#xff0c;Replace…

有趣的事,讲给有趣的人听

哈哈哈&#xff0c;今天不写技术了&#xff0c;今天分享一下生活&#xff0c;技术我们什么时候都可以学&#xff0c;但是生活更值得我们现在就去更好的体验&#xff01; 两年多的涤生大数据&#xff0c;认识了形形色色的小伙伴&#xff0c;陆续沟通下来6000多人&#xff0c;彼时…

Vue框架入门基础知识

什么是Vue&#xff1f; Vue 是一套前端框架&#xff0c;免除原生JavaScript中的DOM操作&#xff0c;简化书写 框架:是一个半成品软件&#xff0c;是一套可重用的、通用的、软件基础代码模型。基于框架进行开发&#xff0c;更加快捷、更加高效。 基于MVVM(Model-View-ViewModel…

看完这篇带你了解大学生必考安全证书NISP详解

NISP证书详解 NISP证书介绍&#xff1a;NISP证书等级&#xff1a;NISP&#xff08;一级&#xff09;报名&#xff1a;NISP&#xff08;一级&#xff09;课程大纲&#xff1a;NISP&#xff08;二级&#xff09;报名NISP&#xff08;二级&#xff09;课程大纲NISP二级置换CISP指南…

Java中的泛型

泛型 什么是泛型泛型类泛型接口泛型方法通配符泛型的上下限 泛型的注意事项擦除问题基本数据类型问题 什么是泛型 定义类、接口、方法时&#xff0c;同时声明了一个或者多个类型变量&#xff08;如&#xff1a;&#xff09;&#xff0c;称为泛型类、泛型接口&#xff0c;泛型方…

说说TCP 3次握⼿和4次握手

三次握手过程 client端建⽴连接&#xff0c;发送⼀个SYN同步包&#xff0c;发送之后状态变成SYN_SENTserver端收到SYN之后&#xff0c;同意建⽴连接&#xff0c;返回⼀个ACK响应&#xff0c;同时也会给client发送⼀个SYN包&#xff0c;发送完成之后状态变为SYN_RCVDclient端收到…

PySide6/PyQt6中的时间管理类:QTime的使用方法

文章目录 📖 介绍 📖🏡 环境 🏡📒 使用方法 📒📝 创建QTime对象📝 常用方法⚓️ 相关链接 ⚓️📖 介绍 📖 QTime是PySide6中用于处理时间段的类,可以用来表示一天中的时间,例如小时、分钟和秒。它提供了许多操作和格式化时间的功能,使得处理时间变得更加…

MATLAB中simulink中scope同时显示两个输入信号

在使用scope时&#xff0c;需要两个输入信号的设置方法 1.点开scope图标 2 点击设置按钮&#xff0c; 然后弹出configuration properties&#xff1a;scope配置图&#xff0c;在Main选项下&#xff0c;在Number of input ports&#xff1a;1这里面更改数字&#xff0c;需要几…

vscode中如何解决 Comments are not permitted(JSON中不允许注释)

vs code中如何解决Comments are not permitted&#xff08;JSON中不允许注释&#xff09;&#xff1f; 简单几步&#xff0c;让你轻松解决。 1.使用vscode打开json文件后&#xff0c;一些注释显示如图所示&#xff0c;有红色波浪线&#xff0c;影响阅读 2. 悬浮在波浪线报错信…

【MySQL】mysql集群

文章目录 一、mysql日志错误日志查询日志二进制日志慢查询日志redo log和undo log 二、mysql集群主从复制原理介绍配置命令 读写分离原理介绍配置命令 三、mysql分库分表垂直拆分水平拆分 一、mysql日志 MySQL日志 是记录 MySQL 数据库系统运行过程中不同事件和操作的信息的文件…

RocketMQ源码阅读-Broker消息接收

RocketMQ源码阅读-Broker消息接收 1. 从单元测试入手2. Broker启动流程3. Broker接收消息4. Broker接收消息时序图5. 小结 Broker接收 Producer发送的消息。 Broker在RocketMQ中也是一个独立的Model&#xff0c;rocketmq-broker。 Broker的核心类为SendMessageProcessor。 …

opencv多张图片实现全景拼接

最近camera项目需要用到全景拼接&#xff0c;故此查阅大量资料&#xff0c;终于将此功能应用在实际项目上&#xff0c;下面总结一下此过程中遇到的一些问题及解决方式&#xff0c;同时也会将源码附在结尾处&#xff0c;供大家参考&#xff0c;本文采用的opencv版本为3.4.12。 首…

一天吃透JVM面试八股文

内容摘自我的学习网站&#xff1a;topjavaer.cn 什么是JVM&#xff1f; JVM&#xff0c;全称Java Virtual Machine&#xff08;Java虚拟机&#xff09;&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。由一套字节码指令集、一组寄存器、一个栈、一个垃圾回…

前端基础知识整理汇总(下)

react 生命周期 React v16.0前的生命周期 初始化(initialization)阶段 此阶段只有一个生命周期方法&#xff1a;constructor。 constructor() 用来做一些组件的初始化工作&#xff0c;如定义this.state的初始内容。如果不初始化 state 或不进行方法绑定&#xff0c;则不需…

Jenkins自动化部署docker

Jenkins自动化部署docker和普通方式构建 docker外挂目录 准备测试服务器docker环境准备jdk环境将上传jar包修改为app.jar对外暴露1000端口启动jar FROM openjdk:8-jdk-alpine ARG JAR_FILE COPY ${JAR_FILE} app.jar EXPOSE 1000 ENTRYPOINT ["java","-jar&q…

spring-boot2.7.8添加swagger

一、新建项目swaggerdemo 二、修改pom.xml 注意修改&#xff1a;spring-boot-starter-parent版本为&#xff1a;2.7.8 添加依赖&#xff1a; springfox-swagger2 springfox-swagger-ui springfox-boot-starter <?xml version"1.0" encoding"UTF-8"…

ruoyi后台管理系统部署-3-安装redis

centos7安装redis 1. yum 安装 查看是否安装了redis yum installed list | grep redis ps -ef | grep redis安装epel 仓库&#xff08;仓库是软件包下载的&#xff0c;类似maven&#xff0c;nuget&#xff09; yum install epel-release搜索 redis 包 yum search redis安装…

剪映国际版,免费无限制使用

随着抖音的爆火短视频的崛起&#xff0c;相信每一个人都感受到了短视频快节奏下的生活洪流。 现如今每个人都能成为自己生活的记录者&#xff0c;每一个人都有掌握着剪辑的基本技能。而剪映就是很多人都会使用的剪辑软件。 相对于PR、AE等剪辑软件来说&#xff0c;作为一款国…
最新文章