【线性dp必学四道题】线性dp四道经典例题【最长上升子序列】、【最长公共子序列】、【最长公共上升子序列(maxv的由来)】【最长公共子串】

news/2024/10/24 2:33:58/

【最长上升子序列】、【最长公共子序列】、【最长公共上升子序列】

    • 最长上升子序列
        • f[i] 表示以i结尾的最长子序列
    • 最长公共子序列
        • f[i][j] 表示 a前i 和 b前j个 最长公共长度
    • 最长公共上升子序列
        • f[i][j]代表所有a[1 ~ i]和b[1 ~ j]中以b[j]结尾的公共上升子序列的集合
    • 最长公共子串

最长上升子序列

在这里插入图片描述

f[i] 表示以i结尾的最长子序列

由于我们遍历到i时候
我们需要比较i前面的数据

我们发现如果i 大于 j

那么i就可以拼接在 j 后面

如果f[j] 就是j最长的了
那就
f[i] = f[j] + 1的长度
所以
f[i] 表示以i结尾的最长子序列

#include<iostream>using namespace std;const int N = 1100;int a[N];
int f[N];
int res = 0;
int n;int main()
{cin >> n;for(int i = 1; i <= n; i++) cin >> a[i];a[0] = -0x3f3f3f3f;for(int i = 1; i <= n; i++){for(int j = 0; j <= i ; j++){if(a[j] < a[i])f[i] = max(f[i],f[j]+1);res = max(res,f[i]);}}cout << res;return 0;
}

最长公共子序列

在这里插入图片描述

f[i][j] 表示 a前i 和 b前j个 最长公共长度

#include<iostream>using namespace std;const int N = 1010;int f[N][N];
char a[N],b[N];
int n,m;int main()
{cin >> n >> m;cin >> a+1 >> b+1;for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){if(a[i]==b[j]){f[i][j] = f[i-1][j-1]+1;}else{f[i][j] = max(f[i-1][j],f[i][j-1]);}}}cout << f[n][m];return 0;
}

最长公共上升子序列

在这里插入图片描述

f[i][j]代表所有a[1 ~ i]和b[1 ~ j]中以b[j]结尾的公共上升子序列的集合

这道题如何理解?

  1. 记住f[i][j] 表示什么
  2. 当b的j和i 相等时,我们常规思路是就在b数组中按着第一道题的逻辑 循环遍历之前的值,但是这样是麻烦的。我们需要一种方法,不需要遍历就知道之前的最大值,可以定义一个变量maxv,如果i和j相等,直接等于maxv,如果不相等,那么f[i][j] = f[i-1][j]
  3. 如果a[i]>b[j]
    那么maxv = max(maxv,f[i-1][j]+1);

maxv的由来
在这里插入图片描述

#include<iostream>using namespace std;const int N = 3030;int f[N][N];
int a[N],b[N];
int n;int main()
{cin >> n;for(int i = 1; i <= n; i++) cin >> a[i];for(int i = 1; i <= n; i++) cin >> b[i];for(int i = 1; i <= n; i++){int maxv = 1;for(int j = 1; j <= n; j++){f[i][j] = f[i-1][j];if(a[i]==b[j]){f[i][j] = maxv;}if(a[i]>b[j])maxv = max(maxv,f[i-1][j]+1);}}int ans = 0;for(int i = 0; i <= n; i++){ans = max(f[n][i],ans);}cout << ans;return 0;
}

最长公共子串

在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <cstring>
using namespace std;const int N = 1e4 + 10;
char str1[N], str2[N];int f[N][N];//注意空间限制为256MB,即为2^(8 + 20) = 2^28个字节,
//而一个int型变量占4个字节,那么最多有2^26个int变量,大约为64000000个变量,而此时定义f[N][N]最多有大于1e8个变量,会爆内存
//更何况还有存字符串的空间int main()
{cin >> str1 + 1 >> str2 + 1;    int len1 = strlen(str1 + 1), len2 = strlen(str2 + 1);int res = 0;for (int i = 1; i <= len1; i++){//如果最后一位为数字if (str1[i] >= '0' && str1[i] <= '9'){for (int j = 1; j <= len2; j++)f[i][j] = 0;continue;    }for (int j = 1; j <= len2; j++){//如果最后一位相同且不为数字if (str1[i] == str2[j])f[i][j] = f[i - 1][j - 1] + 1;else f[i][j] = 0;res = max(res, f[i][j]);}}cout << res << endl;return 0;
}

观察我们在状态计算的过程,第i层循环的值,仅与第i-1层循环的值有关
我们可以联想到01背包的优化,利用滚动数组来简化空间复杂度
既然要用到删除一维空间的优化方法,一定要注意:
二维中:f[i][j] = f[i - 1][j - 1] + 1;
在一维中,由于f[j] = f[j - 1],小的j已经被更新,那么就不是上一层(i-1)的数据了
所以必须从大到小遍历

#include <iostream>
#include <cstring>
using namespace std;const int N = 1e4 + 10;
char str1[N], str2[N];int f[N];int main()
{cin >> str1 + 1 >> str2 + 1;    int len1 = strlen(str1 + 1), len2 = strlen(str2 + 1);int res = 0;//用于保存答案for (int i = 1; i <= len1; i++){//如果最后一位为数字if (str1[i] >= '0' && str1[i] <= '9'){for (int j = 1; j <= len2; j++)f[j] = 0;continue;    }for (int j = len2; j >= 1; j--){//如果最后一位相同且不为数字if (str1[i] == str2[j])f[j] = f[j - 1] + 1;else f[j] = 0;res = max(res, f[j]);}}cout << res << endl;return 0;
}

http://www.ppmy.cn/news/153364.html

相关文章

硬件入门设计

硬件入门设计 常见器件的选型 电阻器器件选型 电阻选型需要注意的参数&#xff1a;阻值、封装、功耗、精度。 电阻选型技巧&#xff1a; 确定电阻安装方式确定电阻阻值。&#xff1a;根据电路计算取值、根据电阻数据手册取值、根据积累经验取值。选择封装和功耗选择电阻精度…

硬件设计-DIY项目分享

今天逛Hackday看到一个有趣的项目&#xff0c;一个外国老兄电脑是双系统&#xff0c;每次切换到win&#xff0c;都需要在系统启动界面手动输入指令&#xff0c;很麻烦。 为了偷懒他设计了一个物理层面的系统切换装置&#xff0c;如下图。 他的主要思路是&#xff0c; 1. 用ST…

主机DIY玩家的必备工具包

前段时间在装机的时候&#xff0c;用到了一款图拉丁吧网友自制的工具包-图吧工具箱&#xff0c;觉得十分不错&#xff0c;这不刚好又赶上年终1212购物节&#xff0c;分享出来&#xff0c;给准备DIY主机的朋友一些参考。 图吧工具箱 图吧工具箱号称是最纯净的硬件工具箱&#…

DDR4原理及硬件设计

DDR4的工作原理以及寻址方式 DDR4是什么&#xff1f; DDR4全称&#xff0c;DDR4-DRAM&#xff0c;与其他DDRDRAM一样&#xff0c;是当前电子系统架构中使用最为广泛的的RAM存储器。 这句话可以分解出3个关键字&#xff1a;存储器、DRAM、DDR4。 先说存储器&#xff0c; 说到…

电脑新手也能学会的diy装机教程

对于刚刚开始接触diy装机的网友来说&#xff0c;组装电脑并不是一件简单的事情&#xff0c;因此很多网友都想了解要怎么组装电脑。其实组装台式电脑的步骤并不难&#xff0c;掌握一定的操作即可&#xff0c;下面小编就给大家分享一个电脑新手也能学会的diy装机教程。 具体的安…

精选汇总 | 硬件DIY

关注星标公众号&#xff0c;不错过精彩内容 作者 | strongerHuang 微信公众号 | 嵌入式专栏 为了方便大家平时公交、地铁、外出办事也能用手机回顾查看文章&#xff0c;我特意用心精选&#xff0c;并分类整理了部分文章&#xff1a; DIY | 用铁丝做Arduino UNO板&#xff08;附…

航模DIY【2】-接收器硬件设计

介绍 本接收器用于配合 Deviation-Transmitter 使用&#xff1a; Deviation-Transmitter遥控器硬件参考&#xff1a;https://github.com/psbec/Deviation-TransmitterHardware Deviation-Transmitter遥控器软件参考&#xff1a;https://github.com/psbec/Deviation-Transmitt…

硬件设计需要的工具

想起了一句话&#xff1a;人和动物的区别就是人会使用工具。工具的使用会让你事半功倍&#xff0c;做设计有时候需要“拿来主义”&#xff0c;毕竟发明“轮子”的时代已经过去。言归正传&#xff0c;本篇文章介绍了作为硬件工程师经常使用的工具软件。 硬件设计的一般流程&…