两个数组的dp---区间dp

1、最长公共子序列

1143. 最长公共子序列 - 力扣(LeetCode)

class Solution 
{//1、状态表示://  经验 + 题目要求//  (1)选取第一个字符串[0,i]区间,以及第二个字符串[0,j]区间,作为研究对象//  (2)根据题目要求,确定状态表示// dp[i][j]:s1的[0,i]区间和s2的[0,j]区间中所有的子序列中,最长公共子序列的长度//2、状态转移方程://  根据最后一个位置的状况,分情况讨论//(1)如果s1[i] == s2[j] == x,那么可以确定,最长的公共子序列一定是以x结尾的//所以dp[i][j] = dp[i-1][j-1] + 1//(2)如果s[i] != s2[j]//那么可以去s1[0,i-1]和s2[0,j],或者s1[0,i]和s2[0,j-1],或者s1[0,i-1]和s2[0,j-1]去找//第一种和第二种都是包含第三种的,但是不干扰,因为求的是max,所以这里可以不要第三种情况//3、初始化://关于字符串的dp问题:有时空串是有研究意义的//引入空串,方便初始化//可以引入一行一列,然后注意下标映射(可以在前面加一个" ",来对应下标),并且此时不会越界//第一行,第一列为0即可。因为空串的长度为0//4、顺序:根据状态转移方程:从上往下,从左往右//return dp[n1][n2];
public:int longestCommonSubsequence(string s1, string s2) {int n1 = s1.size(), n2 = s2.size();s1 = ' ' + s1, s2 = ' ' + s2;vector<vector<int>> dp(n1+1,vector<int>(n2+1));for(int i = 1;i<=n1;i++)for(int j = 1;j<=n2;j++)if(s1[i] == s2[j]) dp[i][j] = dp[i-1][j-1] + 1;elsedp[i][j] = max(dp[i-1][j] , dp[i][j-1]);return dp[n1][n2];}
};

2、不相交的线

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

class Solution 
{//分析:要连线不相交//如果我从两个数组中选出公共子序列的话,那连线肯定不相交//所以本题转换为最长公共子序列的问题//dp[i][j]:从nums1[0,i]和nums2[0,j]中选,最长公共子序列的长度
public:int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {int n1 = nums1.size(), n2 = nums2.size();vector<vector<int>> dp(n1+1,vector<int>(n2+1));for(int i = 1;i<=n1;i++)for(int j = 1;j<=n2;j++)if(nums1[i-1] == nums2[j-1]) dp[i][j] = dp[i-1][j-1] + 1;else dp[i][j] = max(dp[i-1][j],dp[i][j-1]);return dp[n1][n2];}
};

3、不同的子序列

115. 不同的子序列 - 力扣(LeetCode)

class Solution 
{//题目解析:在s的子序列中找t出现的个数//那么可以将t看作公共子序列//1、状态表示//dp[i][j]:在s的区间[0,j]中的子序列中,出现t[0,i]的个数//2、状态转移方程//根据s的子序列的最后一个位置,包不包含s[j]//(1)包含,首先必须s[j] == t[i]--->dp[i][j] = dp[i-1][j-1]//(2)不包含,dp[i][j] = dp[i][j-1]//dp[i][j] = dp[i-1][j-1] + dp[i][j-1]//3、初始化://引入空串//里面的值要保证后续的填表是正确的--->不会越界,填表正确//下标的映射关系--->可以str = ' ' + str     //dp[0][j] = 1;//顺序:dp[i][j]需要左上,和左边//从上往下,从左往右//return dp[t.size()][s.size()]
public:int numDistinct(string s, string t) {int m = t.size(), n = s.size();const int MOD = 1e9 + 7;vector<vector<int>> dp(m+1,vector<int>(n+1));for(int j = 0;j<=n;j++) dp[0][j] = 1;for(int i = 1;i<=m;i++)for(int j = 1;j<=n;j++){dp[i][j] = dp[i][j-1];//不包含if(s[j-1] == t[i-1]) dp[i][j] += dp[i-1][j-1];//包含dp[i][j] %= MOD;}return dp[m][n];}
};

4、通配符匹配

44. 通配符匹配 - 力扣(LeetCode)

class Solution 
{//1、状态表示//dp[i][j]:s[0,i]区间内的子串能否被,p[0,j]区间内的子串匹配//2、状态转移方程://经验:根据最后一个位置的状况,分情况讨论//1):p[j] == 普通字符--->那么p[j]至少需要等于s[i],然后需要p[0,j-1]和s[0,i-1]匹配,则dp[i][j] = s[i] == p[j] && dp[i-1][j-1]//2):p[j] == ? --->?必须匹配最后一个字符,则dp[i][j] = dp[i-1][j-1]//3):p[j] == * --->://  a) * 匹配空字符,dp[i][j] = dp[i][j-1]//  b) * 匹配一个字符,dp[i][j] = dp[i-1][j-1]//  c) * 匹配两个字符,dp[i][j] = dp[i-2][j-1]// ....//  n) * 匹配n个字符,dp[i][j] = dp[i-n][j-1],0 <= n <= i//如果这样做的话,时间复杂度会到n三次方//考虑优化(前提p[j] == *)://方法一:数学方法----等价替换//   dp[i][j] = dp[i][j-1] || dp[i-1][j-1] || dp[i-2][j-1] ......//   则dp[i-1][j] = dp[i-1][j-1] || dp[i-2][j-1] || dp[i-3][j-1] .....//   所以将dp[i-1][j]代入dp[i][j]中//   dp[i][j] = dp[i][j-1] || dp[i-1][j];//方法二:根据状态表示 以及 实际情况,优化状态转移方程//   p[j] == *,匹配空串,dp[i][j] = dp[i][j-1]//   p[j] == *.匹配一个,但是!不把 * 丢掉,则dp[i][j] = dp[i-1][j],因为如果下一个匹配,不需要*,那么*可以匹配空串,不影响//    可以理解为*传递下去//   则dp[i][j] = dp[i][j-1] || dp[i-1][j]//最终----->dp[i][j] = dp[i][j-1] || dp[i-1][j]//3、初始化://引入空串--->多加一行一列//里面的值,要保证后续的填表是正确的//注意下标映射关系,可以str = ' ' + str//dp[0][0] = true;//对于dp[0][j],如果p[0,x]全是*,那么dp[0][0 ~ x]全是true,如果p[x+1]不为*,那么dp[0][x+1 ~ p.size]全为false//4、填表顺序:看状态转移方程//从上往下,从左往右//5、return dp[s.size][p.size]
public:bool isMatch(string s, string p) {int n = s.size(), m = p.size();vector<vector<bool>> dp(n+1,vector<bool>(m+1,false));//初始化dp[0][0] = true;for(int j = 1;j<=m;j++)if(p[j-1] == '*') dp[0][j] = true;else break;for(int i = 1;i<=n;i++)for(int j = 1;j<=m;j++){if(p[j-1] >= 'a' && p[j-1] <= 'z') dp[i][j] = (s[i-1] == p[j-1] && dp[i-1][j-1]);else if(p[j-1] == '?') dp[i][j] = dp[i-1][j-1];else dp[i][j] = dp[i][j-1] || dp[i-1][j];}return dp[n][m];}
};

5、正则表达式匹配

10. 正则表达式匹配 - 力扣(LeetCode)

class Solution 
{//题目解析://a* = 空串 || a || aa || aaa ......// .* = 空串 || . || .. || ... || .........//1、状态表示://经验 + 题目要求//dp[i][j]:s这个字符串[0,i]区间的子串,是否能被p字符串[0,j]区间的子串匹配//2、状态转移方程:// 根据最后一个位置的状态,分情况讨论//(1):如果p[j] == [a,z],if(p[j] == s[i]),dp[i][j] = dp[i-1][j-1],即dp[i][j] = p[j] == s[i] && dp[i-1][j-1]//(2):如果p[j] == '.',p[j]匹配s[i],dp[i][j] = dp[i-1][j-1]//(3):如果p[j] = '*'//  1):如果p[j-1] == '.'://      a)翻译成--空串,dp[i][j] = dp[i][j-2]//      b)翻译成--1个点,dp[i][j] = dp[i-1][j-2]//      c)翻译成--2个点,dp[i][j] = dp[i-2][j-2]//      .......//      n)翻译成--n个点,dp[i][j] = dp[i-n][j-2]//      dp[i][j] = dp[i][j-2] || dp[i-1][j-2] || dp[i-2][j-2] || .....//      如果暴力遍历,时间会到n三方,所以需要优化//    优化方法一:数学方法://      dp[i][j] = dp[i][j-2] || dp[i-1][j-2] || dp[i-2][j-2] || .....//   则:dp[i-1][j] = dp[i-1][j-2] || dp[i-2][j-2] || dp[i-3][j-2] || ....//      将dp[i-1][j]代入dp[i][j]//      --------->则dp[i][j] = dp[i][j-2] || dp[i-1][j]//    优化方法二:状态表示结合实际情况,优化状态转移方程//      .*去匹配s[i]后,不把".*"丢掉,让它继续去匹配s[i-1],s[i-2]....//      这里是假想,没有丢掉".*",因为".*"可以匹配很多个//      那么dp[i][j] = dp[i-1][j]//      .*什么都不匹配,直接丢掉,则dp[i][j] = dp[i][j-2]//      --------->则dp[i][j] = dp[i][j-2] || dp[i-1][j]//  2):p[j-1] == [a,z] == #,(假设这个字母为#)//      直接优化://      a)#*去匹配一个空串,则dp[i][j] = dp[i][j-2]//      b)#*去匹配一个,然后保留,但是需要保证p[j-1] == s[i],然后留着去匹配s[i-1]//          则dp[i][j] = p[j-1] == s[i] && dp[i-1][j]//      -------->则dp[i][j] = dp[i][j-2] || (p[j-1] == s[i] && dp[i-1][j])//  总结:(1)p[j] == s[i],dp[i][j] = dp[i-1][j-1]//        (2)p[j] == '.',dp[i][j] = dp[i-1][j-1]//            合并:if(p[j] == s[i] || p[j] == '.') dp[i][j] = dp[i-1][j-1]//        (3)p[j] == *//            dp[i][j] = dp[i][j-2] || ((p[j-1] == s[i] || p[j-1] == '.') && dp[i-1][j])//3、初始化://引入空串--->多加一行一列//此时填表不会越界//里面的值要保证后续的填表是正确的//注意下标的映射关系//dp[0][0] = true;//dp[i][0] = false;//dp[0][j],如果出现"_*",可以匹配空串,"_*_*_*"也可以,"_*_*__"不可以//  所以,当偶数位置出现连续的*,里面是true,否则之后全是false//4、顺序:由状态转移方程//从上往下,从左往右//5、return dp[s.size()][p.size()]
public:bool isMatch(string s, string p) {int n = s.size(), m = p.size();s = ' ' + s, p = ' ' + p;vector<vector<bool>> dp(n+1,vector<bool>(m+1,false));dp[0][0] = true;for(int j = 2;j<=m;j+=2)if(p[j] == '*') dp[0][j] = true;else break;for(int i = 1; i<= n ;i++)for(int j = 1;j<=m;j++)if(p[j] == '*')dp[i][j] = dp[i][j-2] || ((p[j-1] == s[i] || p[j-1] == '.') && dp[i-1][j]);elsedp[i][j] = (p[j] == s[i] || p[j] == '.') && dp[i-1][j-1];return dp[n][m];}
};

6、交错字符串

97. 交错字符串 - 力扣(LeetCode)

class Solution 
{//1、状态表示://预处理 str = ' ' + str//dp[i][j]:s1[1,i]区间内和s2[1,j]区间内的所有分割子串,能否交错拼接s3[1,i+j]区间字符串//2、状态转移方程:// 根据最后一个位置的状态,分情况讨论://(1) 如果s1[i] != s3[i+j] && s2[j] != s3[i+1],不能拼接,false//(2) 如果s1[i] == s3[i+j],dp[i][j] = dp[i-1][j],即s1[1,i-1],s2[1,j]拼接s3[1,i+j-1]//(3) 如果s2[j] == s3[i+j],dp[i][j] = dp[i][j-1]//(4) 如果 s1[i] == s3[i+j] && s2[j] == s3[i+j],不用管,因为(2)(3)就是(4)的组成//3、初始化://已经预处理过了,多开一行一列//dp[0][0] = true;//dp[0][j]:如果s2和s3对应位置相同,true,只要出现一个不同,那就后面全是false//dp[i][0]:和dp[0][j]同理初始化//4、顺序:从上往下,从左往右//5、return dp[s1.size()][s2.size()]public:bool isInterleave(string s1, string s2, string s3) {int n1 = s1.size(), n2 = s2.size(), n3 = s3.size();if(n1 + n2 != n3) return false;//处理边界情况s1 = ' ' + s1, s2 = ' ' + s2, s3 = ' ' + s3;vector<vector<bool>> dp(n1+1,vector<bool>(n2+1));dp[0][0] = true;for(int j = 1;j<=n2;j++)if(s2[j] == s3[j]) dp[0][j] = true;else break;for(int i = 1;i<=n1;i++)if(s1[i] == s3[i]) dp[i][0] = true;else break;for(int i = 1;i<=n1;i++)for(int j = 1;j<=n2;j++)dp[i][j] = (s1[i] == s3[i+j] && dp[i-1][j]) || (s2[j] == s3[i+j] && dp[i][j-1]);return dp[n1][n2];}
};

7、两个字符串的最小ASCII删除和

712. 两个字符串的最小ASCII删除和 - 力扣(LeetCode)

class Solution 
{//题目解析:找删除的ASCII和最小,那么可以转换为删除后的字符串的ASCII和最大//即:求两个字符串里面,所有的公共子序列里面,ASCII和的最大值---->正难则反//1、状态表示//经验 + 题目要求//dp[i][j]:s1[0,i]和s2[0,j]区间中,所有公共子序列里面,ASCII和的最大值//2、状态转移方程// 根据最后一个字符的状态,来分析状态转移方程//(1) 选了s1[i]和s2[j]-->首先s1[i] == s2[j],dp[i][j] = dp[i-1][j-1] + s1[i](s2[j])//(2) 选了s1[i],没选s2[j]-->dp[i][j-1],这里并不是等于,因为这里dp[i][j-1],这个s[i]也是有选和不选的情况,那么dp[i][j-1]是包含dp[i-1][j-1]的,即(2)包含(4)//(3) 没选s1[i],选了s2[j]-->dp[i-1][j],同理(3)是包含(4)的//(4) s1[i]和s2[j]都没选-->dp[i-1][j-1],(4)是可以不用计算的//3、初始化://引入空串,多加一行一列//dp[0][0] = 0;//dp[0][j] = 0,dp[i][0] = 0;//注意下标映射//4、顺序:从上往下,从左往右//5、找到 dp[s1.size()][s2.size()]//统计s1 + s2的ASCII和sum//return sum - 2*dp[s1.size()][s2.size()]public:int minimumDeleteSum(string s1, string s2) {int n1 = s1.size(), n2 = s2.size();vector<vector<int>> dp(n1+1,vector<int>(n2+1));for(int i = 1;i<=n1;i++)for(int j = 1;j<=n2;j++){dp[i][j] = max(dp[i][j-1],dp[i-1][j]);if(s1[i-1] == s2[j-1])dp[i][j] = max(dp[i][j],dp[i-1][j-1] + s1[i-1]);}int sum = 0;for(auto x : s1) sum += x;for(auto x : s2) sum += x;return sum - 2 * dp[n1][n2];}
};

8、最长重复子数组

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

class Solution 
{//1、状态表示://dp[i][j]:nums1[i]为结尾和nums2[j]为结尾的所有重复子数组中,最长的重复子数组的长度//2、状态转移方程://(1)如果nums1[i] != nums2[j],dp[i][j] = 0;//(2)如果nums1[i] == nums2[j],dp[i][j] = dp[i-1][j-1] + 1;//3、初始化://为了方便填值,多加一行一列//初始化为0//4、顺序:从上往下//5、return dp中的max
public:int findLength(vector<int>& nums1, vector<int>& nums2) {int n1 = nums1.size(), n2 = nums2.size();vector<vector<int>> dp(n1+1,vector<int>(n2+1));int res = INT_MIN;for(int i = 1;i<=n1;i++)for(int j = 1;j<=n2;j++){if(nums1[i-1] == nums2[j-1]) dp[i][j] = dp[i-1][j-1] + 1;res = max(res,dp[i][j]);}return res;        }
};

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

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

相关文章

SCI一区 | Matlab实现NGO-TCN-BiGRU-Attention北方苍鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测

SCI一区 | Matlab实现NGO-TCN-BiGRU-Attention北方苍鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现NGO-TCN-BiGRU-Attention北方苍鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测预测效果基本介绍模型…

解决JavaWeb中IDEA2023新版本无法创建Servlet的问题

出现问题&#xff1a;IDEA右键创建Servlet时&#xff0c;找不到选项 原因分析&#xff1a;IDEA的2023版的已经不支持Servlet了&#xff0c;如果还要使用的话&#xff0c;需要自己创建模板使用 创建模板 右击设置&#xff0c;选择&#xff08;File and Code Templates&#x…

前端基础技术栈教程--HTML、CSS与javascript

在我们身处的这个信息化时代&#xff0c;互联网已成为生活不可或缺的一部分。每当我们打开网站浏览信息时&#xff0c;都离不开三个构建网页的基石&#xff1a;HTML、CSS和JavaScript。这些技术不仅塑造了网页的骨架和外观&#xff0c;更为我们提供了丰富的互动体验。对于渴望掌…

Selenium的简单防反爬和浏览器配置

# Selenium的简单使用&#xff1a;https://zhuanlan.zhihu.com/p/557463669 # 防反爬参考&#xff1a;https://blog.csdn.net/weixin_51368459/article/details/125462178 from selenium import webdriver from selenium.webdriver.edge.options import Options# 设置浏览器驱动…

UNIAPP(小程序)每十个文章中间一个广告

三十秒刷新一次广告 ad-intervals"30" <template><view style"margin: 30rpx;"><view class"" v-for"(item,index) in 100"><!-- 广告 --><view style"margin-bottom: 20rpx;" v-if"(inde…

vue3和vue2项目中如何根据不同的环境配置基地址?

在不同环境下取出的变量的值是不同的, 像这样的变量称为环境变量 为什么要使用环境变量呢? 开发环境生产环境下的接口地址有可能是不一样的&#xff0c;所以我们需要根据环境去配置不同的接口基地址 1、vue2环境变量配置 在根目录创建&#xff1a;.env.development和.env.p…

全栈的自我修养 ———— react中router入门+路由懒加载

router 下载router配置view创建目录配置index.js 下载router npm install react-router-dom配置view 如下将组件倒出 const Login () > {return <div>这是登陆</div> } export default Login创建目录 配置index.js React.lazy有路由懒加载的功能&#xff0…

JS详解-迭代器模式详解两种方法实现

前言&#xff1a; // 迭代协议可以定制对象的迭代行为-分为两个协议&#xff1a;可迭代协议、迭代器协议// 可迭代协议&#xff1a;增加方法[Symbol,.iterator](){}&#xff08;属性名表达式&#xff09;返回符合协议器的对象// 迭代器协议:有next方法的对象&#xff0c;next方…

LLMOps快速入门,轻松开发部署大语言模型

大家好&#xff0c;如今我们能够与ChatGPT进行轻松互动&#xff1a;只需输入提示&#xff0c;按下回车&#xff0c;就能迅速得到回应。然而&#xff0c;这个无缝互动的底层&#xff0c;是一系列复杂而有序的自动执行步骤&#xff0c;即大型语言模型运营&#xff08;LLMOps&…

SpringBoot快速入门笔记(4)

文章目录 一、Vue框架1、前端环境准备2、简介3、快速开始4、事件绑定 二、Vue组件化开发1、NPM2、Vue Cli3、组件化开发4、SayHello自定义组件5、Movie自定义组件 一、Vue框架 1、前端环境准备 编码工具&#xff1a;VSCode 依赖管理&#xff1a;NPM 项目构建&#xff1a;VueCl…

【QT教程】QML与C++的交互

主页 软件开发 QT6 QML高级编程补天云火鸟自动化创作平台您能够创建大约3000 个短视频一天可以轻松创建多达 100 个视频 QML与C的交互 使用AI技术辅助生成 【QT免费公开课】您可以到这里观看大量的QT视频课程 【QT付费视频课程】QT QML C 高级扩展开发 目录 1 QML与C的交互…

c++类和对象三部曲——(3)

目录 前言 运算符重载 如何写出运算符重载&#xff1f; 默认成员函数之赋值重载 特殊情况&#xff1a;前置与后置 特殊情况&#xff1a;友元与"operator<<" 内部类 const成员函数 关于const权限放大与缩小的问题 取地址及const取地址重载 再谈构造函…

NLP学习路线总结

NLP&#xff08;自然语言处理&#xff09;是人工智能领域的一个重要分支&#xff0c;涉及计算机理解和生成人类语言的能力。以下是一份NLP的学习路线总结&#xff1a; 基础知识: 编程语言: 掌握Python或Java等主流编程语言&#xff0c;因为大多数NLP工具和库都是用这些语言编写…

DDOS攻击原理

DDoS&#xff08;分布式拒绝服务&#xff09;攻击是一种常见的网络攻击方式&#xff0c;其目的是使目标服务或资源无法正常提供服务给合法用户。DDoS攻击的基本原理是通过大量的恶意流量或请求&#xff0c;耗尽目标系统的资源&#xff08;如带宽、处理能力等&#xff09;&#…

linux模糊删除文件命令

在Linux中&#xff0c;可以使用find命令配合-name参数和通配符来模糊匹配并删除文件。以下是一个示例命令&#xff0c;用于删除当前目录及子目录下所有包含“example”文本的文件&#xff1a; find . -type f -name *example* -exec rm -f {} \;解释&#xff1a; . 表示当前目…

JDI LCD 驱动时序介绍

1. 引言 绝大多数 STM32 MCU 都可应用于图形界面&#xff0c;而且很多系列还内置图形硬件 LTDC&#xff0c;支持驱动 RGB 接口的 LCD。但是存在少数类型的 LCD&#xff0c;如 JDI 屏&#xff0c;除了 STM32L4P5 支持外&#xff0c;其它 MCU 只能根据屏的接口时序要求&#xff…

数学与人工智能:共舞于数字时代的奥秘

数学&#xff0c;这一源远流长的学科&#xff0c;长久以来一直为人类社会的发展与进步提供了坚实的基础。与此同时&#xff0c;随着科技的迅猛发展&#xff0c;人工智能这一新兴领域正逐渐改变着我们的生活方式。这两者之间&#xff0c;似乎存在着一种难以言喻的紧密联系。本文…

hbuilderX创建的uniapp项目转移到vscode

场景&#xff1a;一直使用hbuilderX开发的朋友想转移到vscode获取更好的TypeScript支持&#xff0c;所以想把整个项目目录拖到vscode进行开发&#xff0c;但发现运行不了&#xff0c;提示没有package.json等&#xff0c;并且不能执行pnpm命令 首先&#xff0c;我们先来看一下h…

软件测试(测试用例详解)(三)

1. 测试用例的概念 测试用例&#xff08;Test Case&#xff09;是为了实施测试而向被测试的系统提供的一组集合。 测试环境操作步骤测试数据预取结果 测试用例的评价标准&#xff1a; 用例表达清楚&#xff0c;无二义性。。用例可操作性强。用例的输入与输出明确。一条用例只有…