Day47 | 动态规划 :线性DP 最长公共子序列最长公共子数组

news2024/11/27 18:28:28

Day47 | 动态规划 :线性DP 最长公共子序列&&最长公共子数组

动态规划应该如何学习?-CSDN博客

本次题解参考自灵神的做法,大家也多多支持灵神的题解

最长公共子序列 编辑距离_哔哩哔哩_bilibili

动态规划学习:

1.思考回溯法(深度优先遍历)怎么写

注意要画树形结构图

2.转成记忆化搜索

看哪些地方是重复计算的,怎么用记忆化搜索给顶替掉这些重复计算

3.把记忆化搜索翻译成动态规划

基本就是1:1转换

文章目录

  • Day47 | 动态规划 :线性DP 最长公共子序列&&最长公共子数组
    • 1143.最长公共子序列
      • 思路分析(子问题):
      • 1.回溯 DFS
      • 2.记忆化搜索
      • 3.1:1翻译为动态规划
    • 718.最长重复子数组
      • 思路:
      • 动态规划
    • 1035.不相交的线
      • 动态规划

1143.最长公共子序列

[1143. 最长公共子序列 - 力扣(LeetCode)](https://leetcode.cn/problems/longest-increasing-subsequence/description/)

思路分析(子问题):

设两个字符串分别是s和t

对应的最后一个字母分别是x和y

dfs(x,y)那就是s以x结尾,t以y结尾的两个字符串的最长公共子序列的长度了

那就有四种情况

1.选x这个字母也选y这个字母

2.不选x不选y

3.选x不选y

4.选y不选x

如果x==y,那肯定就是选x也选y,那肯定就是

dfs(x,y)=dfs(x-1,y-1)+1

如果说x!=y,那么就是剩下三种情况里面取一个最大值

dfs(x,y)=max(dfs(x-1,y-1),dfs(x,y-1),dfs(x-1,y))

再仔细一看,其实

dfs(x,y-1),dfs(x-1,y)包含了dfs(x-1,y-1),所以不需要这个了

dfs(x,y)=max(dfs(x,y-1),dfs(x-1,y))

不明白可以举例

dfs(x,y-1)=max(dfs(x-1,y-1),dfs(x,y-2))

递归边界:

只要x或者y小于0,那么就说明有一个字符串已经没有字母可以选择了,那么就到达了边界。

1.回溯 DFS

1.返回值和参数

i是上面x字母的下标,j是y的下标

dfs(i,j)那就是s以x结尾,t以y结尾的两个字符串的最长公共子序列的长度了

int dfs(int i,int j,string &s,string &t)

2.终止条件

只要有一个小于0就说明没有字符可以选了

if(i<0||j<0)
	return 0;

3.本层逻辑

相等就+1,不相等就三种选一种

		if(s[i]==t[j])
            return dfs(i-1,j-1,s,t)+1;
        else
            return max(dfs(i-1,j,s,t),dfs(i,j-1,s,t));

完整代码:

当然,这是超时的

class Solution {
public:
    int dfs(int i,int j,string &s,string &t)
    {
        if(i<0||j<0)
            return 0;
        if(s[i]==t[j])
            return dfs(i-1,j-1,s,t)+1;
        else
            return max(dfs(i-1,j,s,t),dfs(i,j-1,s,t));
    }
    int longestCommonSubsequence(string text1, string text2) {
        return dfs(text1.size()-1,text2.size()-1,text1,text2);
    }
};
//lambda
class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        function<int(int,int)> dfs=[&](int i,int j)->int{
            if(i<0||j<0)
            return 0;
            if(text1[i]==text2[j])
                return dfs(i-1,j-1)+1;
            else
                return max(dfs(i-1,j),dfs(i,j-1));
        };
        return dfs(text1.size()-1,text2.size()-1);
    }
};

2.记忆化搜索

就是搞一个哈希表dp,全都初始化为-1,每次返回前给哈希表dp赋值,碰到不是-1的那就是算过的,那就直接返回计算过的结果,不需要再次递归了

class Solution {
public:
    int dfs(int i,int j,string &s,string &t,vector<vector<int>> &dp)
    {
        if(i<0||j<0)
            return 0;
        if(dp[i][j]!=-1)
            return dp[i][j];
        if(s[i]==t[j])
            return dp[i][j]=dfs(i-1,j-1,s,t,dp)+1;
        else
            return dp[i][j]=max(dfs(i-1,j,s,t,dp),dfs(i,j-1,s,t,dp));
    }
    int longestCommonSubsequence(string text1, string text2) {
        vector<vector<int>> dp(text1.size(),vector<int>(text2.size(),-1));
        return dfs(text1.size()-1,text2.size()-1,text1,text2,dp);
    }
};
//lambda
class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        vector<vector<int>> dp(text1.size(),vector<int>(text2.size(),-1));
        function<int(int,int)> dfs=[&](int i,int j)->int{
            if(i<0||j<0)
                return 0;
            if(dp[i][j]!=-1)
                return dp[i][j];
            if(text1[i]==text2[j])
                return dp[i][j]=dfs(i-1,j-1)+1;
            else
                return dp[i][j]=max(dfs(i-1,j),dfs(i,j-1));
        };
        return dfs(text1.size()-1,text2.size()-1);
    }
};

3.1:1翻译为动态规划

1.确定dp数组以及下标的含义

dp[i][j]就是dfs(I,j)

下标从1开始,下标0记录的是上面if终止条件里面的(i<0||j<0)的非法状态

2.确定递推公式

和dfs中也是对应的

				if(text1[i]==text2[j])
                    dp[i+1][j+1]=dp[i][j]+1;
                else
                    dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);

3.dp数组如何初始化

都初始化为0即可

vector<vector<int>> dp(text1.size()+1,vector<int>(text2.size()+1,0));

4.确定遍历顺序

从前往后遍历即可

		for(int i=0;i<text1.size();i++)
            for(int j=0;j<text2.size();j++)
                if(text1[i]==text2[j])
                    dp[i+1][j+1]=dp[i][j]+1;
                else
                    dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
        return dp[text1.size()][text2.size()];

完整代码

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        vector<vector<int>> dp(text1.size()+1,vector<int>(text2.size()+1,0));
        for(int i=0;i<text1.size();i++)
            for(int j=0;j<text2.size();j++)
                if(text1[i]==text2[j])
                    dp[i+1][j+1]=dp[i][j]+1;
                else
                    dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
        return dp[text1.size()][text2.size()];
    }
};

718.最长重复子数组

718. 最长重复子数组 - 力扣(LeetCode)

思路:

其实就是最长连续公共子序列,在上一题条件中加了一个连续

递归公式就变成了

if(nums1[i]==nums2[j])
	dp[i+1][j+1]=dp[i][j]+1;

因为要求的是连续,所以只要x和y不相等,那就直接是0

注意一个区别就是这里需要一个变量记录一下最大值,剩下的都一样了

动态规划

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        vector<vector<int>> dp(nums1.size()+1,vector<int>(nums2.size()+1,0));
        int res=0;
        for(int i=0;i<nums1.size();i++)
            for(int j=0;j<nums2.size();j++)
            {
                if(nums1[i]==nums2[j])
                    dp[i+1][j+1]=dp[i][j]+1;
                res=max(res,dp[i+1][j+1]);
            }
        return res;   
    }
};

1035.不相交的线

1035. 不相交的线 - 力扣(LeetCode)

和上面最长公共子序列一个意思,代码就只是把s换成nums1,把t换成nums2,仅此而已

动态规划

class Solution {
public:
    int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
        vector<vector<int>> dp(nums1.size()+1,vector<int>(nums2.size()+1,0));
        for(int i=0;i<nums1.size();i++)
            for(int j=0;j<nums2.size();j++)
                if(nums1[i]==nums2[j])
                    dp[i+1][j+1]=dp[i][j]+1;
                else
                    dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
        return dp[nums1.size()][nums2.size()];
    }
};

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

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

相关文章

SQL 复杂查询

目录 复杂查询 一、目的和要求 二、实验内容 &#xff08;1&#xff09;查询出所有水果产品的类别及详情。 查询出编号为“00000001”的消费者用户的姓名及其所下订单。&#xff08;分别采用子查询和连接方式实现&#xff09; 查询出每个订单的消费者姓名及联系方式。 在…

thread_id_key != 0x7777(`fibers` 包与 Node.js 16 及以上版本存在兼容性问题)

文章目录 fibers4.0.3 与 node-v16.13.2-win-x64 的兼容性1. Node.js 版本兼容性2. 特定包版本 (fibers4.0.3)3. 解决方案和替代方案 结论解决方案 运行yarn serve 启动项目&#xff0c;就会弹出上述错误。 fibers4.0.3 与 node-v16.13.2-win-x64 的兼容性 要判断 fibers4.0.3…

数据结构 (6)栈的应用举例

1. 递归调用 递归函数在执行时&#xff0c;会将每一层的函数调用信息&#xff08;包括局部变量、参数和返回地址&#xff09;存储在栈中。当递归函数返回时&#xff0c;这些信息会从栈中弹出&#xff0c;以便恢复之前的执行状态。栈的后进先出&#xff08;LIFO&#xff09;特性…

网络安全在数字时代保护库存数据中的作用

如今&#xff0c;通过软件管理库存已成为一种标准做法。企业使用数字工具来跟踪库存水平、管理供应链和规划财务。 然而&#xff0c;技术的便利性也带来了网络威胁的风险。黑客将库存数据视为有价值的目标。保护这些数据不仅重要&#xff0c;而且必不可少。 了解网络安全及其…

php常用伪协议整理

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理php常见的伪协议 php伪协议介绍 直观点&#xff0c;就是php可以识别的协议。 类似于我们访问网站的http协议&#xff0c;我们用浏览器访问我们自己本地文件的file协议等。 php可以识别这些协议&#xf…

【软件入门】Git快速入门

Git快速入门 文章目录 Git快速入门0.前言1.安装和配置2.新建版本库2.1.本地创建2.2.云端下载 3.版本管理3.1.添加和提交文件3.2.回退版本3.2.1.soft模式3.2.2.mixed模式3.2.3.hard模式3.2.4.使用场景 3.3.查看版本差异3.4.忽略文件 4.云端配置4.1.Github4.1.1.SSH配置4.1.2.关联…

【SpringBoot】28 API接口防刷(Redis + 拦截器)

Gitee仓库 https://gitee.com/Lin_DH/system 介绍 常用的 API 安全措施包括&#xff1a;防火墙、验证码、鉴权、IP限制、数据加密、限流、监控、网关等&#xff0c;以确保接口的安全性。 常见措施 1&#xff09;防火墙 防火墙是网络安全中最基本的安全设备之一&#xff0c…

零基础学安全--shell脚本学习(1)脚本创建执行及变量使用

目录 学习连接 什么是shell shell的分类 查看当前系统支持shell 学习前提 开始学习 第一种执行脚本方法 ​编辑 第二种执行脚本方法 第三种执行脚本方法 变量声明和定义 ​编辑 查看变量 删除变量 学习连接 声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣…

基于FPGA的FM调制(载波频率、频偏、峰值、DAC输出)-带仿真文件-上板验证正确

基于FPGA的FM调制-带仿真文件-上板验证正确 前言一、FM调制储备知识载波频率频偏峰值个人理解 二、代码分析1.模块分析2.波形分析 总结 前言 FM、AM等调制是学习FPGA信号处理一个比较好的小项目&#xff0c;通过学习FM调制过程熟悉信号处理的一个简单流程&#xff0c;进而熟悉…

“AI玩手机”原理揭秘:大模型驱动的移动端GUI智能体

作者&#xff5c;郭源 前言 在后LLM时代&#xff0c;随着大语言模型和多模态大模型技术的日益成熟&#xff0c;AI技术的实际应用及其社会价值愈发受到重视。AI智能体&#xff08;AI Agent&#xff09;技术通过集成行为规划、记忆存储、工具调用等机制&#xff0c;为大模型装上…

路由策略与路由控制实验

AR1、AR2、AR3在互联接口、Loopback0接口上激活OSPF。AR3、AR4属于IS-IS Area 49.0001&#xff0c;这两者都是Level-1路由器&#xff0c;AR3、AR4的系统ID采用0000.0000.000x格式&#xff0c;其中x为设备编号 AR1上存在三个业务网段A、B、C&#xff08;分别用Loopback1、2、3接…

uniapp开发微信小程序笔记8-uniapp使用vant框架

前言&#xff1a;其实用uni-app开发微信小程序的首选不应该是vant&#xff0c;因为vant没有专门给uni-app设置专栏&#xff0c;可以看到目前Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本&#xff0c;并由社区团队维护 React 版本和支付宝小程序版本。 但是vant的优…

Qt-系统相关(1)事件文件

Qt事件 事件介绍 事件是应⽤程序内部或者外部产⽣的事情或者动作的统称。在 Qt 中使⽤⼀个对象来表⽰⼀个事件。所有的 Qt 事件均继承于抽象类 QEvent。事件是由系统或者 Qt 平台本⾝在不同的时刻发出的。当⽤⼾按下⿏标、敲下键盘&#xff0c;或者是窗⼝需要重新绘制的时候&a…

HarmonyOS4+NEXT星河版入门与项目实战(20)------状态管理@ObjectLink @Observed

文章目录 1、用法图解2、案例实现1、任务类改造2、参数改造变量3、完整代码4、运行效果4、总结1、用法图解 2、案例实现 上一节的案例中,一直有一个功能没有生效,就是任务完成后对应的任务行变灰,任务字体出现中划线删除的效果。而该功能一直不生效的原因就是要改变的数据值…

【小白学机器学习36】关于独立概率,联合概率,交叉概率,交叉概率和,总概率等 概念辨析的例子

目录 1 先说结论 2 联合概率 3 边缘概率 4 (行/列)边缘概率的和 总概率1 5 条件概率 5.1 条件概率的除法公式 5.2 条件概率和联合概率区别 1 先说结论 关于独立概率&#xff0c;联合概率&#xff0c;交叉概率&#xff0c;交叉概率和&#xff0c;总概率 类型含义 …

TCP IP协议和网络安全

传输层的两个协议&#xff1a; 可靠传输 TCP 分段传输 建立对话&#xff08;消耗系统资源&#xff09; 丢失重传netstat -n 不可靠传输 UDP 一个数据包就能表达完整的意思或屏幕广播 应用层协议&#xff08;默认端口&#xff09;&#xff1a; httpTCP80 网页 ftpTCP21验证用户身…

redmi 12c 刷机

刷机历程 一个多月前网购了redmi 12c这款手机, 价格只有550,用来搞机再适合不过了, 拆快递后就开始倒腾,网上有人说需要等7天才能解锁,我绑定了账号过了几天又忍不住倒腾,最后发现这块手机不用等7天解锁成功了,开始我为了获取root权限, 刷入了很火的magisk,但是某一天仍然发现/…

分布式在线评测系统

OnlineJudge 前言所用技术开发环境 1. 需求分析2. 项目宏观结构3. compile_server服务设计3.1 compiler服务设计3.2 runner服务设计3.3 compile_run3.4 compile_server.cpp 4. oj_server服务设计4.1 model设计4.2 view设计4.3 control设计4.3.1 获取题目列表功能4.3.2 获取单个…

政安晨【零基础玩转各类开源AI项目】探索Cursor-AI Coder的应用实例

目录 Cusor的主要特点 Cusor实操 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; Cursor 是 Visual Studio Code 的一个分支。这使我们能够…

第三届航空航天与控制工程国际 (ICoACE 2024)

重要信息 会议官网&#xff1a;www.icoace.com 线下召开&#xff1a;2024年11月29日-12月1日 会议地点&#xff1a;陕西西安理工大学金花校区 &#xff08;西安市金花南路5号&#xff09; 大会简介 2024年第三届航空航天与控制工程国际学术会议&#xff08;ICoACE 2024&a…