C++ day55 判断子序列 不同的子序列

题目1:392 判断子序列

题目链接:判断子序列

对题目的理解

判断字符串s是否为t的子序列

字符串s和字符串t的长度大于等于0,字符串s的长度小于等于字符串t的长度,本题其实和最长公共子序列的那道题很相似,相当于找两个子序列的最长公共序列长度,最终这个最长公共序列的长度是否等于字符串s的长度

进阶:如果有大量的字符串s,s1,s2,....,sk(k>=10亿),依次检查是否为t的子序列

动态规划(编辑距离的入门题目)

动规五部曲

1)dp数组及下标i的含义

dp[i][j]:以i-1为结尾的字符串s和以j-1为结尾的字符串t的最长公共子序列的长度

2)递推公式

if (s[i - 1] != t[j - 1]),此时相当于t要删除元素,如果把当前元素t[j - 1]删除,那么dp[i][j] 的数值就是 看s[i - 1]与 t[j - 2]的比较结果了,即:dp[i][j] = dp[i][j - 1];

3)dp数组初始化

根据dp数组的定义,dp[i][0],dp[0][j]没有意义,但是为了满足递推公式,将其初始化为0,其余下标初始化为任意值均可,在之后的计算会被新值覆盖,但是为了初始化方便,均初始成0

4)遍历顺序

根据递推公式,dp[i][j]由dp[i-1][j-1]和dp[i][j-1]推出,遍历顺序从上到下,从左到右

5)打印dp数组

最终的输出结果是dp[s.size()][t.size()]代表最长相同子序列的长度,因为一定要将字符串s和字符串t遍历完,才能判断字符串是否为字符串s的子序列,要不放过任何一个字符,这样才能确保完整性,不落掉任意一个字符,如果这个长度等于s.size(),说明s是t的子序列,返回true

代码,可以直接使用最长公共子序列的代码,只是在最终返回结果的时候与s.size()比较一下

class Solution {
public:bool isSubsequence(string s, string t) {//定义并初始化dp数组vector<vector<int>> dp(s.size()+1,vector<int>(t.size()+1,0));for(int i=1;i<=s.size();i++){for(int j=1;j<=t.size();j++){if(s[i-1]==t[j-1]) dp[i][j]=dp[i-1][j-1]+1;else dp[i][j]=max(dp[i][j-1],dp[i-1][j]);}}if(dp[s.size()][t.size()]==s.size()) return true;else return false;}
};

代码2,是动规五部曲中递推公式中的那个,因为s是最长公共子序列子序列,所以只在t字符串中考虑是否删除元素从而达到减少字符而和字符串s匹配的目的

class Solution {
public:bool isSubsequence(string s, string t) {//定义并初始化dp数组vector<vector<int>> dp(s.size()+1,vector<int>(t.size()+1,0));int result = 0;for(int i=1;i<=s.size();i++){for(int j=1;j<=t.size();j++){if(s[i-1]==t[j-1]) dp[i][j]=dp[i-1][j-1]+1;else dp[i][j]=dp[i][j-1];result = max(result,dp[i][j]);}}if(result==s.size()) return true;else return false;}
};
  • 时间复杂度:O(n × m)
  • 空间复杂度:O(n × m)

代码也可以这样

class Solution {
public:bool isSubsequence(string s, string t) {//定义并初始化dp数组vector<vector<int>> dp(s.size()+1,vector<int>(t.size()+1,0));for(int i=1;i<=s.size();i++){for(int j=1;j<=t.size();j++){if(s[i-1]==t[j-1]) dp[i][j]=dp[i-1][j-1]+1;else dp[i][j]=dp[i][j-1];}}if(dp[s.size()][t.size()]==s.size()) return true;else return false;}
};

题目2:115 不同的子序列

题目链接:不同的子序列

对题目的理解

返回字符串t在字符串s的子序列中出现的个数   注意说的是s的子序列,不一定连续

题目保证答案符合 32 位带符号整数范围

动态规划

动规五部曲

1)dp数组及下标i的含义

dp[i][j] :以i-1为结尾的字符串s中有以j-1为结尾的字符串t个数

2)递推公式

这一类问题,基本是要分析两种情况

  • 当前两字符串末尾的字母相等,s[i - 1] 与 t[j - 1]相等
  • 当前两字符串末尾的字母不等,s[i - 1] 与 t[j - 1] 不相等

s[i - 1] 与 t[j - 1]相等,dp[i][j]可以有两部分组成,(因为字符串s中,可能会包括相同字母顺序出现多次的情况)

1)使用当前的s[i - 1]匹配t[j-1],因为这两个字母已经相同了,所以不需要考虑当前s子串和t子串的最后一位字母s[i-1]和t[j-1]了,即只需要根据前面的s[i-2]和t[j-2]计算的dp[i-1][j-1]个数继续赋值就行,就看前面计算了多少个就可以了,这个继续向下进行赋值就OK

2)不使用当前的s[i - 1]来匹配t[j-1]

例如: s:bagg 和 t:bag ,s[2],s[3] 和 t[2]是相同的,可以用s[3]来匹配,也可以用s[2]匹配,

当s[3]和t[2]相匹配时,当前的s[i-1]与t[i-1]相匹配都对应着最后一个字母g,此时就是第一种情况,取决于dp[i-1][j-1];

但是不使用s[3](假设删除了元素s[3],也有可能和t相匹配),而是使用s[2]来匹配t[2]也是可以的,字符串t中要匹配的字母t[2]还是不变,只是s子串的最后一个字母发生了变化(由s[3]处的g变为s[2]处的g)而已,个数就为同样的t[j]在前面s[i-2]计算的个数,即对应着dp数组中的dp[i-1][j],

所以当s[i - 1] 与 t[j - 1]相等时,将这两种情况得到的结果进行相加,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];

当s[i - 1] 与 t[j - 1]不相等时,dp[i][j]只有一部分组成

因为两个子串最末尾的字符已经不等了,所以无法使用s[i-1]匹配t[j-1],则对于t[j-1]不考虑s[i-1],模拟将字符串中的s[i-1]这个元素删除,那么就拿上一层,也就是字符s[i-1]的前一个字符s[i-2]来匹配字符t[i-1]的结果来作为当前字符s[i-1]匹配t[j-1]的结果,

dp[i][j] = dp[i - 1][j]

3)dp数组初始化

根据递推公式,dp[i][j]是从上方和左上方推导而来,第一行与第一列要进行初始化,是递推公式的基础。

根据dp数组定义,dp[i][0]   代表以i-1为结尾的字符串s中有以-1为结尾的空字符串t的个数,而s不为空,如果将s中的字符都删除,则会变成空字符串t  ,则有一个

dp[0][j]  代表以-1为结尾的字符串s中有以j-1为结尾的t字符串的个数,此时s是空字符串,而t不是空字符串,所以无论怎么改变s,都没有办法组成t字符串,所以有0个

交集  dp[0][0] = 1 :空字符串s中有1个空i字符串t

4)遍历顺序

根据递推公式  从左到右,从上到下

5)打印dp数组

最终的结果是dp[s.size()][t.size()],因为最终一定要将字符串s和字符串t遍历完,才能最终判定字符串s中有多少个字符串t,这样才能不落掉任何一个字符,保证字符全部都遍历到,这样才能不落掉任何一个个数

代码

class Solution {
public:int numDistinct(string s, string t) {//定义并初始化dp数组vector<vector<int>> dp(s.size()+1,vector<int>(t.size()+1,0));//初始化dp数组for(int i=0;i<s.size();i++) dp[i][0]=1;for(int i=1;i<=s.size();i++){for(int j=1;j<=t.size();j++){if(s[i-1]==t[j-1]) dp[i][j]=dp[i-1][j-1]+dp[i-1][j];else dp[i][j]=dp[i-1][j];}}return dp[s.size()][t.size()];}
};

上述代码会报如下错误

会有溢出错误,因为是两个整数相加,结果超出了int类型的表示范围

将代码改为如下

class Solution {
public:int numDistinct(string s, string t) {//定义并初始化dp数组vector<vector<uint64_t>> dp(s.size()+1,vector<uint64_t>(t.size()+1,0));//初始化dp数组for(int i=0;i<s.size();i++) dp[i][0]=1;for(int i=1;i<=s.size();i++){for(int j=1;j<=t.size();j++){if(s[i-1]==t[j-1]) dp[i][j]=dp[i-1][j-1]+dp[i-1][j];else dp[i][j]=dp[i-1][j];}}return dp[s.size()][t.size()];}
};
  • 时间复杂度: O(n * m)
  • 空间复杂度: O(n * m)

也可以将类型改为unsigned long long也能顺利通过,代码如下

class Solution {
public:int numDistinct(string s, string t) {//定义并初始化dp数组vector<vector<unsigned long long>> dp(s.size()+1,vector<unsigned long long>(t.size()+1,0));//初始化dp数组for(int i=0;i<s.size();i++) dp[i][0]=1;for(int i=1;i<=s.size();i++){for(int j=1;j<=t.size();j++){if(s[i-1]==t[j-1]) dp[i][j]=dp[i-1][j-1]+dp[i-1][j];else dp[i][j]=dp[i-1][j];}}return dp[s.size()][t.size()];}
};

流程

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

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

相关文章

HashMap相关专题

前置知识&#xff1a;异或运算 异或运算介绍 异或有什么神奇之处&#xff08;应用&#xff09;&#xff1f; &#xff08;1&#xff09;快速比较两个值 &#xff08;2&#xff09;我们可以使用异或来使某些特定的位翻转&#xff0c;因为不管是0或者是1与1做异或将得到原值的相…

IntelliJ IDEA 2023.2新特性详解第三弹!Docker、Kubernetes等支持!

9 Docker 在 Docker 镜像层内预览文件 现在可以在 Services&#xff08;服务&#xff09;工具窗口中轻松访问和预览 Docker 镜像层的内容。 从列表选择镜像&#xff0c;选择 Show layers&#xff08;显示层&#xff09;&#xff0c;然后点击 Analyze image for more informati…

ES6对象

1.对象简写 ES6中规定可以直接在对象中写入变量和函数作为对象的属性和方法&#xff0c;此时属性名为变量名, 属性值为变量的值。对象简写在未来的使用频率极其高。 let namelarry;let age12;let obj{name,age,//es5 sayName:function(){}// sayName(){// console.log(t…

<软考>软件设计师-2操作系统(总结)

(一) 进程管理 1 操作系统概述 1-1 操作系统定义: 能有效地组织和管理系统中的各种软/硬件资源&#xff0c;合理地组织计算机系统工作流程&#xff0c;控制程序的执行&#xff0c;并且向用户提供一个良好的工作环境和友好的接口。 1-2 操作系统的作用: 1 通过资源管理提高计…

7+WGCNA+机器学习+实验+泛癌分析,多要素干湿结合

今天给同学们分享一篇生信文章“Analysis and Experimental Validation of Rheumatoid Arthritis Innate Immunity Gene CYFIP2 and Pan-Cancer”&#xff0c;这篇文章发表在Front Immunol期刊上&#xff0c;影响因子为7.3。 结果解读&#xff1a; DEG筛选和数据预处理 数据在…

Helplook VS Google Docs:一对一比较

还记得Google Docs在2006年一炮走红的时候吗&#xff1f;它很大程度地改变了协作方式&#xff0c;也减少了附加文件和频繁保存的麻烦。相比Microsoft Word&#xff0c;很多人更喜欢Google Docs的简单性。 但是时代也在不断地发展。像HelpLook这样的新竞争对手也可以提供先进的…

设计模式总目录

目录 设计模式 1. 创建型模式 1.1 工厂方法模式 1.2 抽象工厂模式 1.3 单例模式 1.4 建造者模式 1.5原型模式 2. 结构型模式 2.1 适配器模式 2.2 装饰器模式 2.3 代理模式 2.4 外观模式 2.5 桥接模式 2.6 组合模式 2.7 享元模式 3. 行为型模式 3.1 策略模式 …

字符集——带你了解UTF-8的前世今生

文章目录 字符集的来历汉字和字母的编码特点Unicode字符集字符集小结编码和解码开发约定 字符集的来历 计算机是美国人发明的&#xff0c;由于计算机能够处理的数据只能是0和1组成的二进制数据&#xff0c;为了让计算机能够处理字符&#xff0c;于是美国人就把他们会用到的每一…

前端面试高频考点—事件循环Event loop

目录 事件循环 执行步骤 概念讲解 主线程 微任务(micro task) 宏任务(macro task) Event Loop经典例题 这段代码的执行结果是什么&#xff1f; 正确答案&#xff1a; 具体流程&#xff1a; 事件循环 主线程从"任务队列"中读取执行事件&#xff0c;这个过程…

通俗讲解分布式锁:场景和使用方法

对于锁大家肯定不会陌生&#xff0c;比如 synchronized 关键字 和 ReentrantLock 可重入锁&#xff0c;一般我们用其在多线程环境中控制对资源的并发访问。但是随着业务的发展&#xff0c;分布式的概念逐渐出现在我们系统中&#xff0c;我们在开发的过程中经常需要进行多个系统…

字符数组和字符串例题

1、相邻字符判相等 题目描述 输入一行字符&#xff08;长度小于等于1000&#xff09;&#xff0c;判断其中是否存在相邻两个字符相同的情形&#xff0c;若有&#xff0c;则输出该相同的字符并结束程序(只需输出第一种相等的字符即可)。否则输出No。 输入要求 输入一行字符&…

File类—递归文件搜索执行脚本文件

文章目录 一、需求分析二、File类2.1 File对象的创建2.2 File判断和获取方法2.3 创建和删除方法2.4 遍历文件夹方法 三、Runtime类—常见api四、递归文件搜索执行脚本文件 一、需求分析 在本篇博客中&#xff0c;我们想通过递归文件的方式&#xff0c;在D:\\判断下搜索QQ.exe这…

麒麟V10安装kerberos客户端

麒麟V10系统安装kerberos客户端 当系统具备yum镜像源的时候需要执行安装命令 yum install krb5-devel krb5-client krb5-libs -y 会提示报错 “未找到匹配的参数:krb5-client” 此时我们需要手动安装krb5-client 安装包链接放到了这里 链接: https://pan.baidu.com/s/1x1YVr6…

SQL Server的安装和首个库的创建

一、熟悉SQL Server的安装环境&#xff1b; 1.安装Microsoft的数据库管理系统SQL Server 2022 先把SQL Server 2022下载好后进行解压后出现以下界面然后点击基本进行安装 然后会出现以下界面&#xff1a; 一步步按照提示往下走即可&#xff0c;把SQL Server 2022安装完成后再…

【1day】Panabit 日志系统openid接口SQL注入漏洞

注:该文章来自作者日常学习笔记,请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 目录 一、漏洞描述 二、资产测绘 三、资产测绘 四、漏洞复现

Leetcode刷题笔记题解(C++):LCR 021. 删除链表的倒数第 N 个结点

思路&#xff1a;用双指针去遍历链表&#xff0c;删除left的下一个节点&#xff0c;注意的是n大于等于链表长度即删除第一个节点 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {…

tmux简单使用

它允许你在一个终端窗口中创建多个终端会话&#xff0c;并在它们之间进行切换。以下是tmux的一些主要用途和功能&#xff1a; 多窗口&#xff1a; Tmux允许你在一个终端中创建多个窗口。每个窗口可以包含一个或多个终端会话&#xff0c;你可以轻松地在这些窗口之间切换。面板分…

ifstream读取txt中的中文数据转成QString出现乱码

使用ifstream从txt文本中读取中文数据到string&#xff0c;再将string转成QString输出时出现了乱码。 分析&#xff1a;如果ifstream能成功从txt文本中读出中文数据&#xff0c;那大概率txt用的编码是ANSI编码&#xff08;GBK就是ANSI的一种&#xff09;&#xff0c;那么在转成…

不愧是字节出来的,太厉害了。。。

前段时间公司缺人&#xff0c;也面了许多测试&#xff0c;一开始瞄准的就是中级水准&#xff0c;当然也没指望能来大牛&#xff0c;提供的薪资在15-20k这个范围&#xff0c;来面试的人有很多&#xff0c;但是平均水平真的让人很失望。看了简历很多上面都是写有4年工作经验&…

Jmeter 接口-加密信息发送(一百九十九)

方式1&#xff1a;使用函数助手 比如MD5加密方式&#xff1a; 如图&#xff0c;需要对${user}进行MD5加密 1、打开函数助手&#xff0c;找到MD5&#xff0c;输入需要加密的值 2、将${__MD5(${user},)}放到请求中 3、查看请求&#xff0c;请求成功 方式2&#xff1a;导入jar包…