115. 不同的子序列 dp入门(一)详细推导dp转移方程式

目录

1. 题目引入:

2. 动态规划解法

2.1 动态dp表示

2.2 动态方程推导:

2.3 具体分析

 2.4 初始化

3. 代码如下

java版

c++版

 Python版


1. 题目引入:

给你两个字符串 s 和 t ,统计并返回在 s 的 子序列 中 t 出现的个数,结果需要对 109 + 7 取模。

示例 1:

输入:s = "rabbbit", t = "rabbit"
输出3
解释:
如下所示, 有 3 种可以从 s 中得到 "rabbit" 的方案rabbbit
rabbbit
rabbbit

示例 2:

输入:s = "babgbag", t = "bag"
输出5
解释:
如下所示, 有 5 种可以从 s 中得到 "bag" 的方案babgbag
babgbag
babgbag
babgbag
babgbag

提示:

  • 1 <= s.length, t.length <= 1000
  • s 和 t 由英文字母组成

2. 动态规划解法

2.1 动态dp表示

dp[i][j] 代表 t 前 i 字符串可以由 s j 字符串组成最多个数.

2.2 动态方程推导:

当 s[j] == t[i] , dp[i][j] = dp[i-1][j-1] + dp[i][j-1];

当 s[j] != t[i] , dp[i][j] = dp[i][j-1]

2.3 具体分析

很多朋友们拿到这种dp数组的题,知道要用动态规划,但是往往有时不知道如何写动态转移方程和初始化赋值。我觉得有两种思考方法,

        --------第一,可以画出dp的数组,自己从中找出规律,然后考虑边界值以及初始化赋值(常用)。

例如:

s = "babgbag", t = "bag"

   

  1.        ~~~ 可以先画出来dp的样子,一般对于字符串的动态规划的题,都是定义dp[i][j]为s为i,t为j时所求问题的子问题的答案,这里先不具体分析初始条件。以先找规律为主。由于字符比较简单,可以自己很快就把这个dp数组填满。
  2.        ~~~可以发现这个规律

    当 S[j] == T[i] , dp[i][j] = dp[i-1][j-1] + dp[i][j-1];

    当 S[j] != T[i] , dp[i][j] = dp[i][j-1]

当然了,一下子写出这个答案对于刚入门动态规划的朋友来说是有点不能接受的。所以可以参考第二种方法 。

    --------第二,直接观察题目所给的字符串,从第一个字符或者最后一个字符来分析。解决最简单的一个问题,然后递推到子问题。有点像递归的分析。其实dp就像是从字问题推到最终问题的递归版本的解法。

还是以s = "babgbag", t = "bag"为例

先假设前面的dp已经推导出来了。

  1. 当最后s,t一个元素相同时:

对于s = "babgba", t = "ba"。我们试图用s="babgba"的子序列来表示t="ba"。这里我们可以两种选择方法

        \bigcirc  选取s = "babgba"来表示t="ba",我们选择s = "babgba"的字符a来表示,此为情况一。

既然我们确定了要选a,就可以只看dp[i-1][j-1]了。就相当于s = "babgba"的a与t="ba"抵消掉了。因为这个两个字符串(s,t)末尾的a是固定的,并不会改变他们各自的前一个状态。

        \bigcirc  选取s = "babgb"来表示t="ba",我们不选择s = "babgba"的字符a来表示,此为情况二。

 问题可以简化为看dp[i][j-1]。具体理解可参考下图

如图我们可以这样选择:

 2.4 初始化

  • j==0时,dp[i][0] = 1
  • i==0时,dp[0][j] = 0

如图举例所示  ‘’为空字符串,即当s为‘’时只能表示‘’,故dp[0][0]=1,s为‘’,其余不为‘’则初始化为0

希望读者可以理解这里为什么是dp[i][j-1],dp[i-1][j-1].如果实在不理解可以对照着表格来写一遍。

3. 代码如下

java版

class Solution {public int numDistinct(String s, String t) {int n1 = s.length();int n2 = t.length();int[][] dp = new int[n2 + 1][n1 + 1];for (int j = 0; j <= n1; j++) {dp[0][j] = 1;}for (int i = 1; i <= n2; i++) {for (int j = 1; j <= n1; j++) {if (t.charAt(i - 1) == s.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1];} else {dp[i][j] = dp[i][j - 1];}}}return dp[n2][n1];}
}

c++版

#include <iostream>
#include <vector>using namespace std;int numDistinct(string s, string t) {int n1 = s.size();int n2 = t.size();vector<vector<int>> dp(n2 + 1, vector<int>(n1 + 1, 0));for (int j = 0; j <= n1; j++) {dp[0][j] = 1;}for (int i = 1; i <= n2; i++) {for (int j = 1; j <= n1; j++) {if (t[i - 1] == s[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1];} else {dp[i][j] = dp[i][j - 1];}}}return dp[n2][n1];
}

 Python版

class Solution:def numDistinct(self, s: str, t: str) -> int:n1 = len(s)n2 = len(t)dp = [[0] * (n1 + 1) for _ in range(n2 + 1)]for j in range(n1 + 1):dp[0][j] = 1for i in range(1, n2 + 1):for j in range(1, n1 + 1):if t[i - 1] == s[j - 1]:dp[i][j] = dp[i - 1][j - 1]  + dp[i][j - 1]else:dp[i][j] = dp[i][j - 1]#print(dp)return dp[-1][-1]

此为初学dp期间的学习与思考,如有不恰当表述之处,欢迎大佬指正!

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

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

相关文章

计算机基础(day1)

1.什么是内存泄漏&#xff1f;什么是内存溢出&#xff1f;二者有什么区别&#xff1f; 2.了解的操作系统有哪些&#xff1f; Windows&#xff0c;Unix&#xff0c;Linux&#xff0c;Mac 3. 什么是局域网&#xff0c;广域网&#xff1f; 4.10M 兆宽带是什么意思&#xff1f;理论…

OAK-FFC 分体式相机使用入门介绍

概述 OAK FFC 主控板和多种可选配镜头模组非常适合灵活的搭建您的3D人工智能产品原型。由于镜头是分体式的&#xff0c;因此你可以根据需要测量的距离&#xff0c;自定义深度相机安装基线&#xff0c;并根据你的项目要求&#xff08;分辨率、快门类型、FPS、光学元件&#xff…

项目风险管理:从理论到实践的探索

项目风险管理&#xff1a;从理论到实践的探索 前言一、项目风险识别二、项目风险应对策略三、综合应对策略结语 前言 在当今快速变化的商业环境中&#xff0c;项目管理已成为组织实现目标的关键工具。然而&#xff0c;项目的成功往往伴随着各种不确定性和潜在风险。有效的风险管…

【Git-驯化】一文搞懂git中rm命令的使用技巧

【Git-驯化】一文搞懂git中rm命令的使用技巧 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档关注&#xff1a;微信公…

五、Spring Boot - 上手篇(1)

&#x1f33b;&#x1f33b;目录 一、快速入门&#xff1a;创建第一个SpringBoot 工程1.1 点击File--->New--->Project...1.2 选择版本和依赖的相关骨架包1.3 设置项目保存目录1.4 项目创建完成&#xff0c;工程主界面如下1.5 项目说明1.6 启动项目1.7 编写 HelloControl…

快速上手,spring boot3整合task实现定时任务

在已经上线的项目中&#xff0c;定时任务是必不可少的。基于spring boot自动装配的原理&#xff0c;我们要集成task定时任务还是非常简单的。只需要简单的两步就可以实现。 1、创建一个spring boot项目&#xff0c;并在项目的启动类&#xff08;也不一定非要是启动类&#xff…

如何排查GD32 MCU复位是由哪个复位源导致的?

上期为大家讲解了GD32 MCU复位包括电源复位和系统复位&#xff0c;其中系统复位还包括独立看门狗复位、内核软复位、窗口看门狗复位等&#xff0c;在一个GD32系统中&#xff0c;如果莫名其妙产生了MCU复位&#xff0c;如何排查具体是由哪个复位源导致的呢&#xff1f; GD32 MC…

【RabbitMQ】MQ相关概念

一、MQ的基本概念 定义&#xff1a;MQ全称为Message Queue&#xff0c;是一种提供消息队列服务的中间件&#xff0c;也称为消息中间件。它允许应用程序通过读写队列中的消息来进行通信&#xff0c;而无需建立直接的连接。作用&#xff1a;主要用于分布式系统之间的通信&#x…

vulntarget-b

实际部署之后centos7 的ip有所变动分别是 :192.168.127.130以及10.0.20.30 Centos7 老规矩还是先用fscan扫一下服务和端口&#xff0c;找漏洞打 直接爆出来一个SSH弱口令…&#xff0c;上来就不用打了&#xff0c;什么意思&#xff1f;&#xff1f;&#xff1f; 直接xshell…

STM32--HAL库--定时器篇

一&#xff1a;如何配置定时器 打开对应工程串口配置好的工程&#xff08;上一篇博客&#xff09;做如下配置&#xff1a; 定时器的中断溢出时间计算公式是&#xff1a; 由图得T100*1000/100MHz 注&#xff1a;100MHz100000000 所以溢出时间等于1ms 关于上图4的自动重装…

【网络安全】文件上传黑白名单及数组绕过技巧

不安全的文件上传&#xff08;Unsafe FileUpload&#xff09; 不安全的文件上传是指Web应用程序在处理用户上传的文件时&#xff0c;没有采取足够的安全措施&#xff0c;导致攻击者可能利用这些漏洞上传恶意文件&#xff0c;进而对服务器或用户造成危害。 目录 一、文件上传…

Unity横板动作游戏 - 素材导入和整理

导入素材 编辑器布局 点击每个窗口右上角的三个点可以有更多的窗口选项。 在屏幕的右上角有一个菜单可以保存布局或读取已经报错的布局。 工具按钮 编辑器上的工具按钮在启动的时候是蓝色的&#xff0c;在不启动的时候是灰色的。 这个按钮将会决定场景中的物体是以锚点显示还…

Oracle配置TCPS加密协议测试

文章目录 一、环境信息二、配置过程1.创建证书2.监听配置2.1.配置sqlnet.ora2.2.配置listener.ora文件2.3.配置tnsnames.ora文件2.4.重载监听 3.数据库本地测试3.1. tcps登录测试3.2.日志监控 一、环境信息 操作系统&#xff1a;Linux 版本信息&#xff1a;Oracle 19c 参考文档…

EXCEL自动公式计算始终为0

如果你的数据单元格的左上角存在绿色的三角小箭头&#xff0c;那么就会造成这种问题&#xff1a; 你的数字是以文本形式存入的单元格 解决办法&#xff1a; 选中数据列&#xff0c;数据->分列 直接选择完成 此时就可以进行公式计算了

pytest结合allure-pytest插件生成测试报告

目录 一、安装allure-pytest插件 二、下载allure 三、生成allure报告 四、效果展示 一、安装allure-pytest插件 二、下载allure 下载之后解压&#xff0c;解压之后还要配置环境变量&#xff08;把allure目录下bin目录配置到系统变量的path路径&#xff09;&#xff0c;下…

企业化运维(8)Docker容器技术

###1.Docker介绍### 什么是Docker Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间…

2024后端开发面试题总结

一、前言 上一篇离职贴发布之后仿佛登上了热门&#xff0c;就连曾经阿里的师兄都看到了我的分享&#xff0c;这波流量真是受宠若惊&#xff01; 回到正题&#xff0c;文章火之后&#xff0c;一些同学急切想要让我分享一下面试内容&#xff0c;回忆了几个晚上顺便总结一下&#…

全栈嵌入式C++、STM32、Modbus、FreeRTOS和MQTT协议:工业物联网(IIoT)可视化系统设计思路(附部分代码解析)

项目概述 随着工业4.0时代的到来&#xff0c;工业物联网&#xff08;IIoT&#xff09;在提高生产效率、降低运营成本和实现智能制造方面得到了广泛应用。本项目旨在开发一个全面的工业物联网监控系统&#xff0c;能够实时监测设备的温度、压力、振动和电流等参数&#xff0c;并…

谷粒商城实战踩坑笔记-Service循环依赖

文章目录 1. 使用 Lazy 注解2. 使用 PostConstruct 注解3&#xff0c;补充循环依赖相关知识循环依赖的原因举例说明 4&#xff0c;Lazy 的工作原理 启动项目失败&#xff0c;原因是出现了循环依赖。 The dependencies of some of the beans in the application context form a …

PP 6 成本中心 活动类型 以及两者的关联

成本中心创建&#xff1a;KS01 保存即可 活动类型&#xff1a;KL01 &#xff08;有准备&#xff0c;机器&#xff0c;工时等&#xff09; 保存 KP26:活动类型和成本中心的关联