IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 浅谈LIS与LCS -> 正文阅读

[数据结构与算法]浅谈LIS与LCS

LIS

首先LIS为最长子序列,我们有一个朴素的DP求LIS,时间规模为O(n2)

代码如下

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <set>
#include <cmath>
#include <map>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int MN = 65005;
const int MAXN = 1000005;
const int INF = 0x3f3f3f3f;
#define IOS ios::sync_with_stdio(false);

int n;
int s[MAXN];
int dp[MAXN];
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", s + i);
	}
	int res = 0;
	for (int i = 1; i <= n; i++) {
		dp[i] = 1;
		for (int j = 1; j <= i; j++) {
			if (s[i] > s[j]) {
				dp[i] = max(dp[i], dp[j] + 1);
			}
		}
		res = max(res, dp[i]);
	}
	printf("%d\n", res);
	return 0;
}

如果要输出路径也很简单,只要在每次DP的时候加一个前驱元素就行,然后通过递归输出路径

但很明显如果N的数据规模变大了将无法在有限时间内解决问题,也就是一种暴力枚举。

此时就要用另一种方法,此时dp[i]代表上升子序列长度为i时最小末尾数值,然后开始遍历序列,如果此时该元素大于目前最大长度的最小末尾数则更新最大长度;

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <set>
#include <cmath>
#include <map>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int MN = 65005;
const int MAXN = 1000005;
const int INF = 0x3f3f3f3f;
#define IOS ios::sync_with_stdio(false);

int a[MAXN];
int f[MAXN];
int main() {
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", a + i);
		f[i] = INF;//方便以后更新最长序列
	}
	f[1] = a[1];
	int len = 1;
	for (int i = 2; i <= n; i++) {
		int l = 0, r = len;
		if (a[i] > f[len]) {
			f[++len] = a[i];//如果大于则更新最长序列
		} else {
			while (r - l > 1) {//用二分查找最后一个小于它的元素,更新它下一个元素的最小末尾数,因为数组内保存的是最小末尾,所以一定是递增的
				int mid = (l + r) >> 1;
				if (f[mid] > a[i]) {
					r = mid;
				} else {
					l = mid;
				}
			}
			f[r] = min(a[i], f[r]);
		}
	}
	printf("%d", len);
	return 0;
}

LCS

?先来看一下最朴素的算法,时间复杂度也是O(n2)规模一大就会被卡

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <set>
#include <cmath>
#include <map>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int MN = 65005;
const int MAXN = 1000005;
const int INF = 0x3f3f3f3f;
#define IOS ios::sync_with_stdio(false);

int dp[105][105];
int a[105];
int b[105];
int n,m;

int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",a+i);
	}
	for(int i=1;i<=m;i++){
		scanf("%d",b+i);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<m;j++){
			if(a[i]==b[j]){
				dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
			}else{
				dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
			}
		}
	}
	printf("%d",dp[n][m]);
	return 0;
}

所以可以来考虑一下O(nlogn)的算法

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <set>
#include <cmath>
#include <map>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int MN = 65005;
const int MAXN = 1000005;
const int INF = 0x3f3f3f3f;
#define IOS ios::sync_with_stdio(false);


const int N = 1e5 + 5;
int a[N], b[N], mp[N], f[N];

int main() {
	int n;
	memset(f, INF, sizeof(f));
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", a + i);
		mp[a[i]] = i;//建立一个B在A中位置的表
	}
	for (int i = 1; i <= n; i++) {
		scanf("%d", b + i);
	}
	int len = 0;
	f[0] = 0;
	for (int i = 1; i <= n; i++) {
		int l = 0, r = len, mid;
		if (mp[b[i]] > f[len]) {//转换为LIS问题,即将B中元素转换为A中元素且带有序号;
			f[++len] = mp[b[i]];
		} else {
			while (r - l > 1) {
				mid = (r + l) >> 1;
				if (f[mid] > mp[b[i]]) {
					r = mid;
				} else {
					l = mid;
				}
			}
			f[l + 1] = min(mp[b[i]], f[l + 1]);
		}
	}
	printf("%d", len);
	return 0;
}

?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-24 00:48:42  更:2022-03-24 00:50:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:25:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码