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

server/2024/10/18 5:31:14/

【模板】最长公共子序列

题目描述

给出 1 , 2 , … , n 1,2,\ldots,n 1,2,,n 的两个排列 P 1 P_1 P1 P 2 P_2 P2 ,求它们的最长公共子序列。

输入格式

第一行是一个数 n n n

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

输出格式

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

样例 #1

样例输入 #1

5 
3 2 1 4 5
1 2 3 4 5

样例输出 #1

3

提示

  • 对于 50 % 50\% 50% 的数据, n ≤ 1 0 3 n \le 10^3 n103
  • 对于 100 % 100\% 100% 的数据, n ≤ 1 0 5 n \le 10^5 n105

题解

LCSTLE_or_MLE_40">普通的LCS解(会TLE or MLE)

这题最开始我想着模版LCS,所以就默写了一个 真模版 LCS上去,(模版LCS问题这里就不讲了,个人觉得是一种数字三角形的变形题目)

python">def Solution1():N = int(input())Nums1 = [0] + list(map(int, input().strip().split()))Nums2 = [0] + list(map(int, input().strip().split()))dp = [[0 for _ in range(N+1)] for _ in range(N+1)]for i in range(1, N+1):for j in range(1, N+1):dp[i][j] = max(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]+1 if Nums1[i] == Nums2[j] else 0)print(dp[N][N])
Solution1()

在这里插入图片描述
我擦,懵了,这特么什么情况,不是模版题吗???

LIS_59">转换成LIS问题

我去查看了几篇题解,这才明白这道题的情况

首先我们看看LIS问题:
举例:

4 5 3 1 6 7 2

求上面这个序列的最长上升子序列

怎么求?
正常的想法就是用最长上升子序列的方法求,贪心解 ( O ( n l o g n ) ) (O(nlogn)) (O(nlogn)),或者dp解 ( O ( n 2 ) ) (O(n^2)) (O(n2)),学过这方面的一般都是懂的,

但是求最长上升子序列问题还有一种思路

求最长上升子序列其实是求最长公共子序列

可能看到这有点懵了
继续举例:

4 5 3 1 6 7 2
1 2 3 4 5 6 7

求上面两个序列的最长公共子序列
我们发现,第一个序列的所有上升子序列,也一定是第二个序列的子序列,因为第二个序列就是1到7的单调排列。故而求最长的上升子序列,也是求最长的公共子序列。也就是说LIS问题可以转换成LCS问题。同理,这种情况的LCS问题也可以转换成LIS问题来解决。那么和这题有什么关系呢?

这题给了这样的一个神奇的限制条件:

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

所以两个序列的数字总数一样为n, 而且是1到n的一种排列

举例:

3 2 1 4 5
5 4 3 2 1

我们假设有这样的一种大于小于情况:5<4<3<2<1
欸,那么上面的最长上升子序列就是3 2 1了!!

看明白了吗?
当我们把Nums2中下标小的数字看成小的数,下标大的数字看成大的数,那么Nums2就成了一种单调递增序列,而且是全排列的

所以就把刚刚上面那种情况复原出来了,也就是说LCS问题可以转换成LIS问题来解决。

下面给出关于这题的LIS贪心解(LIS的dp解不行)

python">def Solution2():N = int(input())Nums1 = list(map(int, input().strip().split()))Nums2 = list(map(int, input().strip().split()))# 将Nums2转换成 1 2 ... 13 14 ... 100 101的单调上升序列idx = [0 for _ in range(N+1)]for i in range(N):idx[Nums2[i]] = i + 1# 在Nums2中,形式上下标大的数比下标小的数大# 转换成求Nums1的最长上升子序列问题f = []LenF = 0for i in range(N):left, right = 0, LenF# 左闭右开while left < right:mid = left + right >> 1# 如果 形式上 f[mid] < Nums1[i] (在idx上表示就是 idx[f[mid]] < idx[Nums1[i]])# 去f的右边找更大的数,直至 形式上 Nums1[i] <= f[mid]if idx[f[mid]] < idx[Nums1[i]]:left = mid + 1else:right = midif len(f) <= right:f.append(Nums1[i])LenF += 1else:f[right] = Nums1[i]print(LenF)
Solution2()

在这里插入图片描述


http://www.ppmy.cn/server/131982.html

相关文章

【C语言刷力扣】1748.唯一元素的和

题目&#xff1a; 法一 解题思路&#xff1a; 由于 nums.length 小于100&#xff0c;新建数组 num[101]&#xff0c;用来遍历存放 nums[i]出现的次数。 int sumOfUnique(int* nums, int numsSize) {int result 0;int num[101] {0}; // memset(num, 0, sizof(num));for (int…

RK3568笔记六十五:LIVE555交叉编译测试

若该文为原创文章,转载请注明原文出处。 在开发项目时有用到LIVE555,使用是其他芯片,功能是LIVE555拉流,通过LVGL显示摄像头数据。 这里记录如何交叉编译,测试一下,为后续增加拉流和推流准备,使用zlmedia也可以,但live555用的比较多。 想实现的是: 一、使用LIVE555…

小猿口算安卓端安装包PK一题秒过关。。。

大家好&#xff0c;我是小黄。 近段时间&#xff0c;越来越多的同学都想去小猿口算里面虐小学生&#xff0c;但是发现越来越多的计算机学生带着科技与他们进行对抗&#xff0c;这样非计算机专业的大学生们​苦不堪言。 现在&#xff0c;非计算机大学生们翻身的机会来了&#…

v-model双向绑定组件通信

给input元素绑定原生input事件&#xff0c;触发input事件时&#xff0c;进而触发update:model-value事件 <template> <Child v-model"lastName" v-if"true"></Child> <p >{{lastName}}</p> </template> <script&g…

如何理解应用 Java 多线程与并发编程?

如何理解应用 Java 多线程与并发编程&#xff1f; 在日常开发中&#xff0c;随着硬件性能的提升&#xff0c;尤其是多核处理器的普及&#xff0c;如何让应用程序更好地利用这些资源&#xff0c;成为每个程序员需要考虑的问题。这时候&#xff0c;多线程与并发编程就显得尤为重…

windows自动化(一)---windows关闭熄屏和屏保

电脑设置关闭屏幕和休眠时间不起作用解决方案 一共三个方面注意&#xff1a; 一、关闭屏保设置&#xff1a; 二、电源管理设置 三、关闭盖子不做操作&#xff1a; 第一点很重要&#xff0c;就算二三都做了&#xff0c;一没做&#xff0c;照样不行。

OKHTTP 如何处理请求超时和重连机制

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c;主要职责&#xff1a;测试开发、CI/CD 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。 &#x1f60a; 座右铭&#xff1a;不…

【优选算法】(第三十一篇)

目录 最⻓公共前缀&#xff08;easy&#xff09; 题目解析 讲解算法原理 编写代码 最⻓回⽂⼦串(medium) 题目解析 讲解算法原理 编写代码 最⻓公共前缀&#xff08;easy&#xff09; 题目解析 1.题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 2.题…