子序列问题集合

news2024/11/25 0:57:39

子序列问题

  • 最长公共子序列:
  • 最长上升子序列(要输出序列,和最大长度)
    • 1.dp
    • 2.贪心+二分
  • 导弹拦截 (最长上升/下降子序列长度)

最长公共子序列:

在这里插入图片描述


class Solution {
public:
	//dfs(i,j)代表s串i前字符和t串j前个字符,的公共子序列长度

	//假设最长公共子序列是lcs,则当s[i]==t[j]时,那么公共子序列长度因该是+1
	//不同时,如果s[i]在lcs中则dfs(i,j-1),  否则t[j]在lcs中则dfs(i-1,j)
	//也有可能s[i]和t[j]都不在lcs中,那么就是dfs(i-1,j-1)
	//但是显然这个能构造出来的最长公共子序列是小于上面两个的
	// int dfs(string& s,string& t,int i,int j)
	// {
	//     if(i<0||j<0)return 0;
	//     if(s[i]==t[j])
	//     return dfs(s,t,i-1,j-1)+1;
	//     else
	//     return max(dfs(s,t,i-1,j),dfs(s,t,i,j-1));
	// }
	//     int longestCommonSubsequence(string s, string t) {
	//         return dfs(s,t,s.size()-1,t.size()-1);
	//     }
	// };这样朴素的暴搜,显然会超时,并且可以很直观的发现,这里进行了很多重复的操作

	//用二维数组记录之前的结果,dfs+记忆化
	int cache[1005][1005];
	int dfs(string& s, string& t, int i, int j)
	{
		if (i < 0 || j < 0)return 0;
		int& ans = cache[i][j];
		if (ans != 0)return ans;//不为0说明已经确定过这个值了,不必dfs

		if (s[i] == t[j])
			return ans = dfs(s, t, i - 1, j - 1) + 1;
		else
			return ans = max(dfs(s, t, i - 1, j), dfs(s, t, i, j - 1));
		//return dfs(s,t,i,j);
	}
	int longestCommonSubsequence(string s, string t) {
		return dfs(s, t, s.size() - 1, t.size() - 1);
	}
};

最长上升子序列(要输出序列,和最大长度)

在这里插入图片描述
两种解法:

1.dp

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

/*
* 最长不下降子序列
* 1.状态描述
* dp[i]:是以i为结尾的最长不下降子序列的长度
* 2.状态转移方程
* if(a[i]>=a[j]) dp[i]=max(dp[i],dp[j]+1);
* j是i之前的元素
*/

int n, a[201], dp[201], pre[201];

void reverse_print(int index)
{
	if (index == -1)return;
	reverse_print(pre[index]);
	cout << a[index] << " ";
}

/*

14
13 7 9 16 38 24 37 18 44 19 21 22 63 15

*/

int main()
{
	memset(pre, -1, sizeof(pre));
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
		dp[i] = 1;//初始化
	}
	int maxx = 1;//最大长度至少都是1
	int maxIndex = 0;
	for (int i = 1; i < n; i++)
	{
		for (int j = 0; j < i; j++)
		{
			/*if (a[i] >= a[j])//如果只是求解序列长度,这样即可,但是要去找到这个序列,那还需要去记录其前驱
				dp[i] = max(dp[i], dp[j] + 1);
			maxx = max(maxx, dp[i]);*/

			if (a[i] >= a[j])
			{
				if (dp[j] + 1 > dp[i])//说明以j为前驱时,会得到更长的序列,此时更新pre[i]
				{
					dp[i] = dp[j] + 1;
					pre[i] = j;
				}
			}
			if (dp[i] > maxx)
			{
				maxx = dp[i];
				maxIndex = i;
			}
		}
	}
	std::cout << "max=" << maxx << endl;
	reverse_print(maxIndex);
	return 0;
}

2.贪心+二分

/*解法一:贪心+二分 */
class Solution {
public:
	int low_bound(vector<int>& arr, int key)//去找一个最小的大于key的
	{
		int left = 0, right = arr.size();

		while (left < right)
		{
			int mid = (left + right) / 2;
			if (arr[mid] < key)
				left = mid + 1;
			else if (arr[mid] > key)//当mid大于key时,不是让right=mid-1;因为有可能此时的mid就是最小的大于key的
				right = mid;
		}
		return right;
	}
	int lengthOfLIS(vector<int>& nums) {
		vector<int> ret;//ret[i]表示长度为i+1的子序列的最小值
		/*
		我尽可能让这个子序列的末尾元素小,这样后面更多的元素才可能加入
		*/
		ret.push_back(nums[0]);//一个必然升序
		for (int i = 1, k = 1; i < nums.size(); i++)//k是此时ret中有多少个元素,作为下标使用k-1
		{
			if (nums[i] > ret[k - 1])//大于ret的结尾,ret的结尾是ret中的最大的,直接加入
			{
				ret.push_back(nums[i]);
				k++;

			}
			else if (nums[i] < ret[k - 1])//遇到小于,则往前去找一个最小的并且大于的num[i]的ret
			{
				int pos = low_bound(ret, nums[i]);//这里使用二分,提高效率
				//cout << "pos=" << pos << endl;
				//if (ret[pos] == nums[i])continue;
				ret[pos] = nums[i];
			}
		}
		return ret.size();
	}
};

导弹拦截 (最长上升/下降子序列长度)

在这里插入图片描述

/*
* 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数,导弹数不超过1000),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

389 207 155 300 299 170 158 65

6
2

其实就是去求这个序列的最长上升子序列的长度,和最长下降子序列的长度
*/

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

int n = 1, a[1001], dp_up[1001], dp_down[1001];
int main()
{
	while (cin >> a[n])
	{
		dp_up[n] = dp_down[n] = 1;
		n++;
	}
	n--;
	int max_down = 1, max_up = 1;
	for (int i = 2; i <= n; i++)
	{
		for (int j = 1; j < i; j++)
		{
			if (a[i] > a[j])dp_up[i] = max(dp_up[i], dp_up[j] + 1);
			if (a[i] <= a[j])dp_down[i] = max(dp_down[i], dp_down[j] + 1);
		}
		max_down = max(max_down, dp_down[i]);
		max_up = max(max_up, dp_up[i]);
	}
	cout << max_down << endl << max_up << endl;
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言自定义类型详解(1)结构体知识汇总

本篇概要 本篇主要讲述C语言结构体的相关知识&#xff0c;包括结构体的基本声明&#xff0c;结构体的匿名结构&#xff0c;结构体的自引用&#xff0c;结构体变量的定义和初始化以及结构体的内存对齐等相关知识。 文章目录 本篇概要1.结构体1.1结构体的基本声明1.2结构体的特殊…

应用程序转换工具Unite mac中文版软件特点

Unite mac是一款Mac平台上的应用程序转换工具&#xff0c;它可以将任何网站或Web应用程序转换成本地应用程序&#xff0c;以便更方便地访问和使用。 Unite mac软件特点 网站转应用程序&#xff1a;该软件可以将任何网站或Web应用程序转换成本地应用程序&#xff0c;方便用户更…

AI创作工具-AI创作工具技术解读

创作是广告、文章、小说、社交媒体内容等各个领域的关键&#xff0c;但它通常需要创作者花费大量时间和精力&#xff0c;思考、编写和编辑内容。有时候&#xff0c;创作者可能面临写作灵感枯竭、时间紧迫或需要大量内容的情况。 添加图片注释&#xff0c;不超过 140 字&#xf…

Java集合--Collection、Map、List、Set、Iterator、Collections工具类

文章目录 一、Java集合框架概述二、Collection接口方法2.1、Collection子接口一&#xff1a;List2.1.1、ArrayLIst的源码分析2.1.2、LinkedList的源码分析2.1.3、List接口中的常用方法 2.2、Collection子接口二&#xff1a;Set2.2.1、Set接口的无序性2.2.2、添加元素的过程&…

Leetcode---363周赛

题目列表 2859. 计算 K 置位下标对应元素的和 2860. 让所有学生保持开心的分组方法数 2861. 最大合金数 2862. 完全子集的最大元素和 一、计算k置为下标对应元素的和 简单题&#xff0c;直接暴力模拟&#xff0c;代码如下 class Solution { public:int sumIndicesWithKS…

从零开始学习CTF,看完不信你学不会!

一、CTF简介 简介 中文一般译作夺旗赛&#xff08;对大部分新手也可以叫签到赛&#xff09;&#xff0c;在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式 CTF起源于1996年DEFCON全球黑客大会&#xff0c;以代替之前黑客们通过互相发起真实攻击进行技术…

Linux——文件系统

✅<1>主页&#xff1a;&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux——文件系统 ☂️<3>开发环境&#xff1a;Centos7 &#x1f4ac;<4>前言&#xff1a;上期我们了解了文件在内存中得组织方式&#xff0c;那么文件在磁盘中…

ElasticSerach+MongoDB:实现文章检索历史功能

实现目标&#xff1a; 展示用户的搜索记录10条&#xff0c;按照搜索关键词的时间倒序可以删除搜索记录保存历史记录&#xff0c;保存10条&#xff0c;多余的则删除最久的历史记录 数据库的选择&#xff1a; 用户的搜索记录&#xff0c;需要给每一个用户都保存一份&#xff0c;数…

第3讲:vue路由安装配置,带参路由,子路由配置及应用

路由的安装与基本使用 vue-router是Vue官方的路由插件,它和Vue是深度集成,适用于构建单页面应用 vue-router的安装 //vue2路由配置npm install vue-router@3.0.2 或 cnpm install vue-router@3.0.2在具体应用的开发中我们一般会在src目录下新建一个名为router的目录,并在r…

加速乐源码(golang版本)

一、分析 分析过程网上有很多,这里只说个大概,主要是提供golang源码 请求网站,发现前两次请求都会返回521,第三次请求成功,说明前两次请求肯定是干了什么事情;使用接口请求工具模拟请求分析该过程 使用postman工具请求 a. 第一次请求会在响应头返回jsluid,返回内容中拼接…

滚动轴承 调心球轴承 外形尺寸

声明 本文是学习GB-T 281-2013 滚动轴承 调心球轴承 外形尺寸. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了符合 GB/T 273.3—1999 的调心球轴承及带紧定套的调心球轴承(以下简称轴承)的 外形尺寸。 本标准适用于调心球轴承…

【数字IC/FPGA】基于握手的数据广播

简介 本文介绍了一种基于握手协议的数据广播方式。事实上,该场景可以简化为模块的一对多握手,并且下游的各个模块可以独立的完成握手(与之相对的是下游模块一起完成握手,相比之下,下游各个模块可以独立完成握手显然更加普适、灵活)。 下图展示了模块一对多握手的示意图:…

阿里云服务器经济型e实例详细介绍_e系列性能价格表

阿里云服务器ECS推出经济型e系列&#xff0c;经济型e实例是阿里云面向个人开发者、学生、小微企业&#xff0c;在中小型网站建设、开发测试、轻量级应用等场景推出的全新入门级云服务器&#xff0c;CPU采用Intel Xeon Platinum架构处理器&#xff0c;支持1:1、1:2、1:4多种处理…

GLTF编辑器如何合并相同材质的Mesh

1、什么是模型材质合批 模型材质合批是一种技术手段&#xff0c;主要用于优化渲染性能和提高图形应用程序的帧率。它通过将多个模型的材质进行合并&#xff0c;从而减少渲染时的绘制调用次数。 在计算机图形学中&#xff0c;每个模型都有一个或多个材质&#xff0c;这些材质定义…

【教程】视频汇聚/视频监控管理平台EasyCVR录像存储功能如何优化?具体步骤是什么?

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。视频监控系统EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、云存储、…

使用 PyTorch 的计算机视觉简介 (5/6)

一、说明 本文主要介绍CNN中在pytorch的实现&#xff0c;其中VGG16网络&#xff0c;数据集来源&#xff0c;以及训练过程&#xff0c;模型生成和存储&#xff0c;模型调入等。 二、预训练模型和迁移学习 训练 CNN 可能需要大量时间&#xff0c;并且该任务需要大量数据。但是&am…

【每日一题】441. 排列硬币

441. 排列硬币 - 力扣&#xff08;LeetCode&#xff09; 你总共有 n 枚硬币&#xff0c;并计划将它们按阶梯状排列。对于一个由 k 行组成的阶梯&#xff0c;其第 i 行必须正好有 i 枚硬币。阶梯的最后一行 可能 是不完整的。 给你一个数字 n &#xff0c;计算并返回可形成 完整…

位段 联合体 枚举

Hello好久不见&#xff0c;今天分享的是接上次结构体没有分享完的内容&#xff0c;这次我们讲讲位段 枚举和联合体的概念以及他们的用法。 2.1 什么是位段 位段的声明和结构是类似的&#xff0c;有两个不同&#xff1a; 1.位段的成员必须是 int、unsigned int 或signed int 。 …

Unity下tga和png格式图片打包成AB包大小和加载速度测试

测试素材 测试素材&#xff0c;一张tga格式&#xff0c;一张png格式&#xff0c;他们的图像尺寸一样都是8K图。 两张图在AssetBundles里显示 Tga格式的图明显大很多&#xff0c;我们打包成ab包看看。 在PC 打包后看&#xff0c;明显大小一样&#xff0c;我们进行ab包加载&am…

通俗易懂讲解拥塞控制

文章目录 前言一、拥塞控制是什么&#xff1f;二、什么是拥塞窗口&#xff1f;和发送窗口有什么关系呢&#xff1f;三、慢启动四、阻塞避免算法五、拥塞发生状态时的算法以及快速重传以及快速恢复总结 前言 TCP的拥塞控制&#xff0c;以前觉得老复杂了&#xff0c;今天重温了一…