【C++刷题】优选算法——动态规划第五辑

  1. 最长公共子序列
状态表示:选取第一个字符串[0,i]区间和第二个字符串[0,j]区间作为研究对象dp[i][j]: 表示s1的[0,i]区间和s2的[0,j]区间内的所有子序列中,最长公共子序列的长度
状态转移方程:text1[i] == text2[j]:dp[i][j] = dp[i-1][j-1] + 1;text1[i] != text2[j]:dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
int longestCommonSubsequence(string text1, string text2)
{// 1.dp数组vector<vector<int>> dp(text1.size(), vector<int>(text2.size()));// 2.初始化if(text1[0] == text2[0]) dp[0][0] = 1;for(int i = 1; i < text1.size(); ++i){if(text1[i] == text2[0]) dp[i][0] = 1;else dp[i][0] = dp[i-1][0];}for(int j = 1; j < text2.size(); ++j){if(text2[j] == text1[0]) dp[0][j] = 1;else dp[0][j] = dp[0][j-1];}// 3.状态转移方程for(int i = 1; i < text1.size(); ++i){for(int j = 1; j < text2.size(); ++j){if(text1[i] == text2[j])dp[i][j] = dp[i-1][j-1] + 1;elsedp[i][j] = max(dp[i-1][j], dp[i][j-1]);}}// 4.返回值return dp.back().back();
}
  1. 不相交的线
状态表示 & 状态转移方程: 参考1.最长公共子序列
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2)
{// 1.dp数组vector<vector<int>> dp(nums1.size(), vector<int>(nums2.size()));// 2.初始化if(nums1[0] == nums2[0]) dp[0][0] = 1;for(int i = 1; i < nums1.size(); ++i){if(nums1[i] == nums2[0]) dp[i][0] = 1;else dp[i][0] = dp[i-1][0];}for(int j = 1; j < nums2.size(); ++j){if(nums2[j] == nums1[0]) dp[0][j] = 1;else dp[0][j] = dp[0][j-1];}// 3.状态转移方程for(int i = 1; i < nums1.size(); ++i){for(int j = 1; j < nums2.size(); ++j){if(nums1[i] == nums2[j]) dp[i][j] = dp[i-1][j-1] + 1;else dp[i][j] = max(dp[i][j-1], dp[i-1][j]);}}// 4.返回值return dp.back().back();
}
  1. 不同的子序列
状态表示:dp[i][j]: 表示 s 字符串 [0, i] 区间内的所有子序列中,有多少个 t 字符串 [0, j] 区间子串
状态转移方程:s[i] == t[j]: dp[i][j] = dp[i-1][j] + dp[i-1][j-1]s[i] != t[j]: dp[i][j] = dp[i-1][j]
int numDistinct(string s, string t)
{// 1.dp数组vector<vector<unsigned int>> dp(s.size(), vector<unsigned int>(t.size()));// 2.初始化if(s[0] == t[0]) dp[0][0] = 1;for(int i = 1; i < s.size(); ++i){if(s[i] == t[0]) dp[i][0] = dp[i-1][0] + 1;else dp[i][0] = dp[i-1][0];}// 3.状态转移方程for(int i = 1; i < s.size(); ++i){for(int j = 1; j < t.size(); ++j){if(s[i] == t[j]) dp[i][j] += dp[i-1][j-1];dp[i][j] += dp[i-1][j];}}// 4.返回值return dp.back().back();
}
  1. 通配符匹配
状态表示:dp[i][j]: 表示字符模式p的[0,j]区间子串,能否匹配字符串s的[0,i]区间子串
状态转移方程:p最后一个字符是英文字符:dp[i][j] = p[j] == s[i] && dp[i-1][j-1]p最后一个字符是'?':dp[i][j] = dp[i-1][j-1]p最后一个字符是'*':dp[i][j] = dp[i-1][j] || dp[i][j-1]
bool isMatch(string s, string p)
{// 1.dp数组vector<vector<bool>> dp(s.size() + 1, vector<bool>(p.size() + 1, false));// 2.初始化// p[0] - ""dp[0][0] = true;// s[0] = ""for(int j = 1; j <= p.size(); ++j){if(p[j-1] == '*') dp[0][j] = true;            else break;}// 3.状态转移方程for(int i = 1; i <= s.size(); ++i){for(int j = 1; j <= p.size(); ++j){if(isalpha(p[j-1])){if(p[j-1] == s[i-1] && dp[i-1][j-1]) dp[i][j] = true;}else if(p[j-1] == '?'){if(dp[i-1][j-1]) dp[i][j] = true;}else{// 方式一dp[i][j] = dp[i-1][j] || dp[i][j-1];// 方式二// for(int k = 0; k <= i; ++k)// {//     if(dp[k][j-1])//     {//         dp[i][j] = true;//         break;//     }// }}}}// 4.返回值return dp.back().back();
}
  1. 正则表达式匹配
状态表示:dp[i][j]: 表示字符规律p的[0,j]区间子串,能否匹配字符串s的[0,i]区间子串
bool isMatch(string s, string p)
{// 0.预处理s = " " + s;p = " " + p;// 1.dp数组vector<vector<bool>> dp(s.size(), vector<bool>(p.size(), false));// 2.初始化// p[0]dp[0][0] = true;// s[0]for(int j = 2; j < dp[0].size(); j += 2){if(p[j] == '*') dp[0][j] = true;else break;}// 3.状态转移方程for(int i = 1; i < dp.size(); ++i){for(int j = 1; j < dp[0].size(); ++j){if(isalpha(p[j])){if(p[j] == s[i] && dp[i-1][j-1]) dp[i][j] = true;}else if(p[j] == '.'){if(dp[i-1][j-1]) dp[i][j] = true;}else{if(p[j-1] == '.'){dp[i][j] = dp[i][j-2] || dp[i-1][j];}else{dp[i][j] = dp[i][j-2] || (p[j-1] == s[i] && dp[i-1][j]);}}}}// 4.返回值return dp.back().back();
}
  1. 交错字符串
状态表示:dp[i][j]: 表示s1中[1,i]区间子串和s2中[1,j]区间子串能否拼凑成s3中[1,i+j]区间子串
bool isInterleave(string s1, string s2, string s3)
{// 0.预处理if(s3.size() != s1.size() + s2.size()) return false;s1 = " " + s1;s2 = " " + s2;s3 = " " + s3;// 1.dp数组vector<vector<bool>> dp(s1.size(), vector<bool>(s2.size()));// 2.初始化dp[0][0] = true;for(int j = 1; j < dp[0].size(); ++j){if(s2[j] == s3[j]) dp[0][j] = true;else break;}for(int i = 1; i < dp.size(); ++i){if(s1[i] == s3[i]) dp[i][0] = true;else break;}// 3.状态转移方程for(int i = 1; i < dp.size(); ++i){for(int j = 1; j < dp[0].size(); ++j){if((s1[i] == s3[i+j] && dp[i-1][j])|| (s2[j] == s3[i+j] && dp[i][j-1]))dp[i][j] = true;}}// 4.返回值return dp.back().back();
}
  1. 两个字符串的最小ASCII删除和
问题转化:求两个字符串所有公共子序列的ASCII码值最大和
状态表示:dp[i][j]: 表示s1的[0,i]区间和s2的[0,j]区间内的所有子序列中,公共子序列的ASCII码值最大和
int minimumDeleteSum(string s1, string s2)
{// 0.预处理int sum = 0;for(char c : s1) sum += c;for(char c : s2) sum += c;s1 = " " + s1;s2 = " " + s2;// 1.dp数组vector<vector<int>> dp(s1.size(), vector<int>(s2.size()));// 2.初始化// 3.状态转移方程for(int i = 1; i < dp.size(); ++i){for(int j = 1; j < dp[0].size(); ++j){if(s1[i] == s2[j]) dp[i][j] = dp[i-1][j-1] + s1[i];if(dp[i-1][j] > dp[i][j]) dp[i][j] = dp[i-1][j];if(dp[i][j-1] > dp[i][j]) dp[i][j] = dp[i][j-1];}}// 4.返回值return sum - 2 * dp.back().back();
}
  1. 最长重复子数组
状态表示:dp[i][j]: 表示num1中以i位置元素为结尾的所有子数组和num2中以j位置元素为结尾的所有子数组中,最长重复子数组的长度
int findLength(vector<int>& nums1, vector<int>& nums2)
{// 1.dp数组vector<vector<int>> dp(nums1.size() + 1, vector<int>(nums2.size() + 1));// 2.初始化// 3.状态转移方程int ret = 0;for(int i = 1; i < dp.size(); ++i){for(int j = 1; j < dp[0].size(); ++j){if(nums1[i-1] == nums2[j-1]) dp[i][j] = dp[i-1][j-1] + 1;ret = max(ret, dp[i][j]);} }// 4.返回值return ret;
}

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

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

相关文章

【进程地址空间】地址空间理解存在原因 | 深入理解页表写时拷贝虚拟地址

目录 地址空间深入理解 划分区域 理解地址空间 地址空间存在的意义 意义1 意义2 意义3 理解页表和写时拷贝 页表 写时拷贝 OS识别错误 理解虚拟地址 fork解释 上篇我们简单的学习了进程地址空间/页表/物理地址/虚拟地址/写时拷贝等概念。本篇深入理解下。 地址空…

算法训练营day20

一、最大二叉树 class Solution {public TreeNode constructMaximumBinaryTree(int[] nums) {//记录最大值的索引&#xff0c;左侧是左子树&#xff0c;右侧是右子树&#xff1b;//然后记录左子树的起始和终止索引,也记录右子树的起始和终止的索引&#xff0c;然后递归//循环条…

Ubuntu系统下 Nvidia驱动 + cuda驱动 + CuDNN安装与卸载

Ubuntu系统下 Nvidia驱动 cuda驱动 CuDNN安装与卸载 一、NVIDIA驱动与CUDA驱动的区别二、NVIDIA驱动安装与卸载1. 查看系统内核版本2. 查看显卡型号3. 查看是否有显卡驱动4. 禁用nouveau并重启5. 卸载旧版本6. 安装&#xff11;&#xff1a;使用标准Ubuntu仓库进行自动化安装…

学习笔记Day21:转录组差异分析

转录组差异分析 差异分析难点在于将数据处理成需要的格式 表达矩阵 数值型矩阵-count 行名是symbol 低表达量的基因需要过滤 分组信息 因子&#xff0c;对照组在level第一位 与表达矩阵的列一一对应 项目名称 字符串&#xff08;不要有特殊字符&#xff09; TCGA-XX…

路由策略实验

一.实验拓扑图&#xff1a; 二.实验要求&#xff1a; 1.按照图示配置IP地址&#xff0c;R1,R3,R4上使用loopback口模拟业务网段 2.R1和R2运行RIPv2&#xff0c;R2&#xff0c;R3和R4运行OSPF&#xff0c;各自协议内部互通 3.在RIP和OSPF间配置双向路由引入&#xff0c;要求除R4…

PHP 函数的命名空间是否会影响执行顺序?

在 php 中&#xff0c;函数命名空间一般不会影响执行顺序。执行顺序通常由文件顺序或函数调用顺序决定。即使函数位于不同的命名空间中&#xff0c;只要它们在同一文件中&#xff0c;它们就会按照定义顺序执行。 PHP 函数命名空间是否会影响执行顺序&#xff1f; 简介 在 PHP…

pygame 烟花效果

# 初始化 pygame.init() screen_width 800 screen_height 600 screen pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption(烟花效果) # 焰火发射 particles [] # 焰火粒子 def firework(x, y): num_particles 100 # 每次发射的…

关于ResNet的假说

ResNet 最核心的思想就是 恒等映射吧 那么现在来提出几个问题&#xff1a; 为什么deeper 以后train L 会增加&#xff1f;恒等映射会解决什么问题&#xff1f;能否解决梯度非常陡峭的问题&#xff1f;你想到了什么模型有类似的问题&#xff0c;如何进行改进的&#xff1f; as…

本地环境通过ssh通道连接服务器数据库,实现本地客户端和代码可以访问数据库

使用方法&#xff1a; ssh -p 搭建隧道的端口 -fNL 本地端口:远程ip:远程端口号 搭建隧道的账号搭建隧道的ip 可以增加参数-v,输出更多的信息 ssh -p 搭建隧道的端口 -fNL 本地端口:远程ip:远程端口号 -v 搭建隧道的账号搭建隧道的ip 有时候&#xff0c;测试环境的数据库不允许…

ClickHouse 数据类型、表引擎与TTL

文章目录 数据类型表引擎1.TinyLog 引擎2.MergeTree 引擎3.ReplacingMergeTree 引擎4.AggregatingMergeTree 引擎5.SummingMergeTree 引擎6.CollapsingMergeTree 引擎7.Distributed 引擎 TTL列级 TTL表级TTL 数据类型 ClickHouse 数据类型Java 数据类型数据范围UInt8Short0 到…

【ETOJ P1023】同鱼系 题解(数学+取余)

题目描述 给定一个大小为 n n n 的数组 a a a 和一个整数 k k k。 你可以执行以下操作任意次&#xff08;0次也行&#xff09;: 选择一个下标 i i i 满足 1 ≤ i ≤ n − k 1 \leq i \leq n-k 1≤i≤n−k&#xff0c;然后交换 a i a_i ai​ 和 a i k a_{ik} aik​。…

获取肖博数学全套视频+讲义

肖博数学是一个专业团队&#xff0c;教学方法非常颠覆&#xff0c;具有很多技巧&特殊的解题方法内容&#xff0c;能使得学生在高考时冲刺高分 hello&#xff0c;今天分享一下高中数学资料&#xff0c;肖博数学&#xff0c; 他们的教学方法与传统的教学方式有所不同&#…

vue实现周日历 日历按周切换 vue日程管理

实现的功能 1、点击今天&#xff1a;回到今日日期并选中今日日期&#xff0c;查当天数据 2、点击左箭头&#xff1a;切换上一周 3、点击右箭头&#xff1a;切换下一周 4、黄圆圈代表有日程提醒&#xff0c;点击选中&#xff0c;下方对应显示当前日程提醒的内容&#xff0c;没有…

Spring Cloud Zuul面试题

Spring Cloud Zuul面试题 1. Zuul概述1.1 什么是Zuul&#xff1f;1.2 Zuul有哪些核心功能&#xff1f;1.3 Zuul 1和Zuul 2有什么区别&#xff1f;1.4 为什么我们需要使用API网关如Zuul&#xff1f; 2. 路由功能2.1 Zuul是如何实现路由的&#xff1f;1. 集成 Zuul2. 配置路由3. …

C++设计模式|创建型 4.建造者模式

1.什么是建造者模式? 建造者模式&#xff08;也被成为生成器模式&#xff09;&#xff0c;是一种创建型设计模式&#xff0c;软件开发过程中有的时候需要创建很复杂的对象&#xff0c;而建造者模式的主要思想是将对象的构建过程分为多个步骤&#xff0c;并为每个步骤定义一个…

nlp 自然语言处理的dataset数据库积累

下面的这个和 entity recognition有关的。 Weights & Biases

mybatis的一二级缓存

MyBatis 给我们提供了一级缓存和二级缓存机制来提高查询效率和减少数据库交互次数&#xff0c;一级缓存主要用于单次数据库会话内的查询优化&#xff0c;而二级缓存则着眼于整个应用层面的数据复用。 一级缓存&#xff08;Local Cache&#xff09; 特点&#xff1a; 一级缓存是…

Java Collections类、Stream流

Collections类 Java中的Collections类是一个功能丰富的工具类&#xff0c;它提供了一系列静态方法来操作和处理集合。以下是一些主要的功能&#xff1a; 创建集合&#xff1a;可以使用Collections类创建空集合、单元素集合以及不可变集合等。这为集合的初始化提供了便利。排序…

3i平台体验性能加持,13600KF+B760M+撼与科技A770 TITAN装机体验

在2022年&#xff0c;intel重启显卡线&#xff0c;带来了多款性价比十分不错的显卡。而近段时间&#xff0c;又有传言说intel第二代产品e即将面世&#xff0c;甚至已经有数款Battlemage GPU曝光&#xff0c;让不少intel忠实粉丝直呼期待&#xff0c;或许在今年年底&#xff0c;…

mysql面试题八(SQL语句)

目录 1.SQL 基本组成部分 常用操作示例 创建表 插入数据 查询数据 更新数据 删除数据 创建索引 授予用户权限 2.常见的聚合查询 1. 计数&#xff08;COUNT&#xff09; 2. 求和&#xff08;SUM&#xff09; 3. 平均值&#xff08;AVG&#xff09; 4. 最大值&…