当前位置: 首页 > wzjs >正文

山西住房和城乡建设部网站首页做原油期货关注什么网站

山西住房和城乡建设部网站首页,做原油期货关注什么网站,石家庄新闻最新消息今天,wordpress邮件发送类✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨ 文章所属专栏:动态规划篇–CSDN博客 文章目录 一.双序列类DP解题步骤 二.例题1.最长公共子序列2.不相交的…

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨
✨ 个人主页:余辉zmh–CSDN博客
✨ 文章所属专栏:动态规划篇–CSDN博客

在这里插入图片描述

文章目录

  • 一.双序列类DP
    • 解题步骤
  • 二.例题
    • 1.最长公共子序列
    • 2.不相交的线
    • 3.不同的子序列
    • 4.通配符匹配
    • 5.正则表达式
    • 6.交错字符串
    • 7.两个字符串的最小ASCLL码删除和
    • 8.最长重复子数组

一.双序列类DP

双序列通常是两个字符串或者两个数组,处理这类的DP,通常涉及到比较,匹配或转换操作。

解题步骤

  • 1.状态表示

    一般是二维数组,表示处理到两个序列的某个位置时的状态。

  • 2.状态转移方程

    从某段区间分析,根据当前字符是否相等以及可能的操作(如替换,插入,删除)来决定状态如何转换。

  • 3.初始化

    对于两个序列,都存在为空的情况,需要单独处理为空的状态值。

  • 4.填表顺序

    根据状态转移方程用到前状态的位置来决定填表顺序,按顺序填充状态表。

  • 5.返回值

    根据题意要求和状态表示确定返回值,可能是返回最后一个状态值也可能是找到状态表中的最大值等。

二.例题

1.最长公共子序列

题目

在这里插入图片描述

算法原理

本道题属于该类型的模板题,最经典的二维状态表表示双序列的状态,后面的题都是在此基础上进行变形。

对于双序列的分析,都是根据某段区间的情况,推出状态转移方程。

在这里插入图片描述

代码实现

int longestCommonSubsequence(string s1, string s2){int m = s1.size(), n = s2.size();//状态表示 dp[i][j]表示s1[0,i]区间和s2[0,j]区间的所有公共子序列中,最长的公共子序列长度//添加第0行和第0列,表示空字符串//初始化为0vector<vector<int>> dp(m + 1, vector<int>(n + 1));//使下标映射正确s1 = ' ' + s1;s2 = ' ' + s2;//填表for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){//状态转移方程 分情况讨论if (s1[i] == s2[j]){dp[i][j] = dp[i - 1][j - 1] + 1;}else{dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);}}}//返回值return dp[m][n];
}

2.不相交的线

题目

在这里插入图片描述

在这里插入图片描述

算法原理

根据题意,将两个数组中相同的数字两线,但是不能存在相交的连线,要求找到最多的连线。转换一下其实就是找两个数组的最长公共子序列的长度,这样的连线一定不会存在相交。所以本道题和上面一道题可以说是完全相同,连状态表示和状态转移的推导都一样,只不过上一题是两个字符串,本道题是两个数组,但是处理方式还是一样的,这里就不再重复讲解,可以根据上一题的讲解来看。

代码实现

int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2){int m = nums1.size(), n = nums2.size();//状态表示 dp[i][j]表示nums1区间[0,i]和nums2区间[0,j]可以连线的个数//初始化 初始值设置为0vector<vector<int>> dp(m + 1, vector<int>(n + 1));//填表for (int i = 1; i <= m; i++){for (int j = 1; j <= n; 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[m][n];
}

3.不同的子序列

题目

在这里插入图片描述

算法原理

本道题是判断其中一个字符串中有多少个子串和另一个字符串相等,还是从某段区间分析。

状态表示: dp[i][j]表示s区间[0,j]内的所有子序列中有多少个和t区间[0,i]的子串相等。

初始化: 添加第0行和第0列 第0行表示t字符串为空,则s字符串中一定存在一个子序列空串与t字符串相等,第0行初始值设置为1;第0列表示s字符串为空,则s字符串一定不存在子序列与t字符串相等,第0列初始值设置为0。

状态转移方程:根据当前字符s[j]包含还是不包含分情况讨论,如果不包含,找剩余区间中的相等个数(dp[i][j-1]);如果包含,需要先判断当前位置字符是否相等(s[j-1]==t[i-1]),然后找剩余区间中的相等个数(dp[i-1][j-1]);两种情况的个数相加就是当前位置的状态值。

填表顺序:从第一行到最后一行,其中每一行从左往右。

返回值:dp[n][m],其中m是s字符串的长度,n是t字符串的长度。

代码实现

const int num = 1000000007;
int numDistinct(string s, string t){int m = s.size(), n = t.size();//状态表示 dp[i][j]表示s区间[0,j]内的所有子序列中有多少个和t区间[0,i]的子串相等//初始化 添加第0行和第0列 第0行表示t字符串为空,则s字符串中一定存在一个子序列空串与t字符串相等,第0行初始值设置为1//第0列表示s字符串为空,则s字符串一定不存在子序列与t字符串相等,第0列初始值设置为0vector<vector<int>> dp(n + 1, vector<int>(m + 1));for (int i = 0; i <= m; i++){dp[0][i] = 1;}//填表for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){//如果不包含当前s[j]字符dp[i][j] = dp[i][j - 1];//如果包含当前s[j]字符 需要先判断是否相等if (s[j - 1] == t[i - 1]){dp[i][j] += dp[i - 1][j - 1];}dp[i][j] %= num;}}//返回值return dp[n][m];
}

4.通配符匹配

题目

在这里插入图片描述

算法原理

本道题属于两个字符串的匹配问题,先从某段区间考虑,分析某段区间的匹配情况,从而推导出状态转移方程。因为算法原理较复杂,这里用画图讲解,如图所示:

在这里插入图片描述

代码实现

bool isMatch(string s, string p){int m = s.size(), n = p.size();//状态表示 dp[i][j]表示p[0,j]区间的子串能否匹配s[0,i]区间的子串vector<vector<bool>> dp(m + 1, vector<bool>(n + 1,false));//使下标映射正确s = " " + s;p = " " + p;//初始化dp[0][0] = true;for (int j = 1; j <= n; j++){if(p[j]=='*'){dp[0][j] = true;}else{break;}}//填表for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){//状态转移方程 分情况讨论if (p[j] == '*'){dp[i][j] = dp[i - 1][j] || dp[i][j - 1];}else{dp[i][j] = (p[j] == '?' || p[j] == s[i]) && dp[i - 1][j - 1];}}}//返回值return dp[m][n];
}

5.正则表达式

题目

在这里插入图片描述

算法原理

本道题和上一题属于一类两个字符串的匹配问题,和上一题其实还是有点相似的,状态表示其实还是相同,根据某段区间的匹配情况来分析,只是状态转移方程中某些情况的分析不同,这里还是用画图讲解,如图所示:

在这里插入图片描述

代码实现

bool isMatch(string s, string p){int m = s.size(), n = p.size();//状态表示 dp[i][j]表示p[0,j]区间的子串能否匹配s[0,i]区间的子串//添加第0行和第0列表示两个字符串为空的情况vector<vector<bool>> dp(m + 1, vector<bool>(n + 1));//使下标映射正确s = " " + s;p = " " + p;//初始化dp[0][0] = true;for (int j = 2; j <= n; j += 2){if (p[j] == '*'){dp[0][j] = true;}//遇到非星号直接结束,剩余全为falseelse{break;}}//填表for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){//状态转移方程 分情况讨论if (p[j] == '*'){dp[i][j] = dp[i][j - 2] || (p[j - 1] == '.' || p[j - 1] == s[i]) && dp[i - 1][j];}else{dp[i][j] = (p[j] == '.' || p[j] == s[i]) && dp[i - 1][j - 1];}}}//返回值return dp[m][n];
}

6.交错字符串

题目

在这里插入图片描述

在这里插入图片描述

算法原理

本道题虽然是三个字符串,但是第三个字符串是由前两个字符串拼接而成的,所以还是属于两个字符串类的DP问题,这里还是从某段区间考虑,分析前两个字符串的某段区间的子串能否拼接成第三个字符串的某段区间的子串。这里用画图讲解,如图所示:

在这里插入图片描述

代码实现

bool isInterleave(string s1, string s2, string s3){int m = s1.size(), n = s2.size();//预处理 下标0表示空串的情况s1 = " " + s1;s2 = " " + s2;//状态表示 dp[i][j]表示s1[1,i]区间的子串和s2[1,j]区间的子串能否拼成s3[1,i+j]区间的子串vector<vector<bool>> dp(m + 1, vector<bool>(n + 1,false));//初始化dp[0][0] = true;for (int i = 1; i <= m; i++){if (s1[i] == s3[i]){dp[i][0] == true;}else{break;}}for (int j = 1; j <= n; j++){if (s2[j] == s3[j]){dp[0][j] = true;}else{break;}}//填表for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){//状态表示 根据s3最后一个字符分两种情况,满足其中一种即可//不能用两个if语句判断dp[i][j] = (s1[i] == s3[i + j] && dp[i - 1][j]) || (s2[j] == s3[i + j] && dp[i][j - 1]);}}//返回值return dp[m][n];
}

7.两个字符串的最小ASCLL码删除和

题目

在这里插入图片描述

算法原理

本道题第一眼可能没什么思路,但是反着来看就会比较简单,这里用到了正难则反的思想。如果反着来看就是找两个字符串的公共子序列最大ASCLL码和,然后用两个字符串总的ASCLL码和减去二倍的公共子序列中的最大ASCLL码和(这里减去二倍是因为存在两个字符串,需要减去两次公共子序列的最大ASCLL码和),因此本道题就转换成了找两个字符串的公共子序列的最大ASCLL码和。还是从某段区间来分析。

状态表示: dp[i][j]表示s1区间[0,i]和s2区间[0,j]的所有子序列中,最大ASCLL码和的公共子序列。

初始化:添加第一行,表示s1为空串的情况,添加第一列,表示s2为空串的情况,当其中一个为空串时,公共子序列也为空,最大ASCLL码和就为0,所以初始值全部设置为0。

状态转移方程:根据两个字符串最后一个位置的字符s1[i]s2[j]选还是不选分情况讨论,第一种情况:如果两个相等选一个即可,就找前一个位置的状态然后加上当前字符的ASCLL码;第二种情况:如果不相等,选择s1[i]字符,找剩余区间内的状态值(dp[i-1][j]);第三种情况:如果不相等,选择s2[j]字符,找剩余区间内的状态值(dp[i][j-1]);第四种情况:如果不相等,两个都不选,找剩余区间内的状态值(dp[i-1][j-1]),但是这种情况在第二种和第三种情况中都已经包括该区间,所以可以省去。最后取三种情况中的最大值。

填表顺序:从第一行到最后一行,其中每一行从左往右。

返回值:两个字符串总的ASCLL码和减去二倍的公共子序列中的最大ASCLL码和(sum-2*dp[m][n])。

代码实现

int minimumDeleteSum(string s1, string s2){//正难则反思想 找两个字符串的公共子序列最大ASCLL码和int m = s1.size(), n = s2.size();//状态表示 dp[i][j]表示s1区间[0,i]和s2区间[0,j]的所有子序列中,最大ASCLL码和的公共子序列//添加第一行,表示s1为空串的情况,添加第一列,表示s2为空串的情况vector<vector<int>> dp(m + 1, vector<int>(n + 1));//填表for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){//状态转移方程dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);if (s1[i - 1] == s2[j - 1]){dp[i][j] = max(dp[i - 1][j - 1] + s1[i-1], dp[i][j]);}}}//统计两个字符串总的ASCLL码和int sum = 0;for(auto ch : s1){sum += ch;}for(auto ch : s2){sum += ch;}//返回值,总的和减去两个最大和公共子序列就是需要最小删除的和return sum - 2 * dp[m][n];
}

8.最长重复子数组

题目

在这里插入图片描述

算法原理

本道题第一眼看可能会觉得和最长公共子序列差不多,都是要找两个数组或字符公共的,但是这里有一个不同点,对于最长公共子序列那道题要找的是子序列,而本道题要找到是子数组,这两个的区别就是,子数组以nums[i]为结尾时,前一个必须是nums[i-1],相邻值才是子数组;而子序列以nums[i]为结尾时,前一个不一定是nums[i-1],可以是nums[i-2]也可以是nums[i-3]等等许多情况。因此本道题的状态表示就不能和前面的几道题一样,从某段区间中的子序列分析,而是必须以当前位置元素为结尾来分析。

状态表示 dp[i][j]表示nums1以i位置元素为结尾和nums2以j位置元素为结尾的公共子数组中的,最长的公共子数组长度

初始化 添加第0行和第0列,表示两个数组为空数组的情况,初始值设置为0

状态转移方程:根据两个数组当前位置元素来分析,如果nums[i-1]==nums[j-1](因为添加了第0行和第0列,映射到原数组中下标要减一),只需找到以前一个位置元素为结尾时的最长公共子数组长度(dp[i-1][j-1])然后加一即可。如果nums[i-1]!=nums[j-1],因为状态表示是以当前位置元素为结尾的公共子数组,既然结尾的两个元素都不想等,所以就不存在公共子数组,长度就为0。

填表顺序:从第一行到最后一行,其中每一行从左往后。

返回值:因为不知道最长的公共子数组是以哪个位置元素为结尾的,所以需要遍历整个状态表,找到最大值返回。

代码实现

int findLength(vector<int>& nums1, vector<int>& nums2){int m = nums1.size(), n = nums2.size();//状态表示 dp[i][j]表示nums1以i位置为结尾和nums2以j位置为结尾的公共子数组中的,最长的公共子数组长度//初始化 添加第0行和第0列,表示两个数组为空数组的情况,初始值设置为0vector<vector<int>> dp(m + 1, vector<int>(n + 1));//返回值 因为不确定最长的公共子数组以那两个位置为结尾,所以需要找到状态表中的最大值int ret = 0;//填表for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){if (nums1[i - 1] == nums2[j - 1]){dp[i][j] = dp[i - 1][j - 1] + 1;}ret = max(ret, dp[i][j]);}}return ret;
}

以上就是关于双序列类DP例题的讲解,如果哪里有错的话,可以在评论区指正,也欢迎大家一起讨论学习,如果对你的学习有帮助的话,点点赞关注支持一下吧!!!
在这里插入图片描述


文章转载自:

http://EEX7wmis.Lsfzq.cn
http://09tQAVHQ.Lsfzq.cn
http://gky10A0x.Lsfzq.cn
http://PNkhcrc8.Lsfzq.cn
http://dTVQh0JM.Lsfzq.cn
http://xIuPfqsp.Lsfzq.cn
http://d9Lkfved.Lsfzq.cn
http://9cqnfc1x.Lsfzq.cn
http://jltYzgbC.Lsfzq.cn
http://tLCCYV1A.Lsfzq.cn
http://A1K6FbLc.Lsfzq.cn
http://hROcEotN.Lsfzq.cn
http://bfwzyLeS.Lsfzq.cn
http://RVSnSWuW.Lsfzq.cn
http://h3xnRRyW.Lsfzq.cn
http://1MJNTeyE.Lsfzq.cn
http://qoMbyNvA.Lsfzq.cn
http://EFe8lqEC.Lsfzq.cn
http://zOx7xaTo.Lsfzq.cn
http://pky3mIn9.Lsfzq.cn
http://gLgocxUn.Lsfzq.cn
http://hXM8IfCq.Lsfzq.cn
http://rG1c5hC1.Lsfzq.cn
http://uti7qccB.Lsfzq.cn
http://g8v3z6rA.Lsfzq.cn
http://ye2UpW1O.Lsfzq.cn
http://kjPmZFEy.Lsfzq.cn
http://unz4yO2K.Lsfzq.cn
http://2LXzAcAt.Lsfzq.cn
http://MbU0ihtV.Lsfzq.cn
http://www.dtcms.com/wzjs/649562.html

相关文章:

  • 颍上网站建设网站建设需求分析调研调查表
  • 墨子学院网站建设vip课程做网站备案的问题
  • 自治区住房和城乡建设厅网站江西建设厅网站电子
  • 《网站开发与应用》大作业营销策划培训
  • 三明网站优化四川seo平台
  • 有没有电商设计的网站参考php做的网站怎么加密
  • 网站专题分类长沙百度seo排名
  • 哪个网站可以做中文云文字厦门云端企业网站建设
  • 网站打不开显示asp网站对联广告代码
  • 撩人的网站怎么做怎么做监控直播网站
  • 了解公司的网站企业所得税优惠政策最新2023计算
  • html5 音乐网站哪个网站做简历比较好
  • 广州建站软件重庆渝北做网站哪里便宜
  • 有那个网站可以做免费的投票网站快速备案
  • 廊坊网页模板建站西安旅游攻略知乎
  • 做网站实例教程简单网页模板免费下载
  • 德阳建设局网站企业网站有哪些平台
  • 网站项目风险建站行业前景
  • 做网站需要注册的那种站酷网怎么赚钱
  • 企业网站有哪些优点汉中城乡建设网站
  • 宁波微网站建设wordpress 图片跳转
  • 网站网站设计的公司东莞短视频推广多少钱
  • 贵州建设职业技术学院官方网站静态网站html模板下载
  • wordpress可以建网站吗随州做网站公司
  • 企业宣传网站系统建设方案网址在手机上怎么登录
  • 安徽建站管理系统开发织梦5.7cms照明灯具能源电子产品企业网站源码企业模板带后台
  • 做网站推广的流程企业网站建立网络虚拟社区时对于企业
  • 网站方案设计与论证自媒体注册平台
  • 百度响应式网站怎么做wordpress备份文件后缀
  • wordpress标签使用自己做网站seo