LeetCode题目115:不同子序列

题目描述

给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。

一个字符串的子序列是指,通过删除一些(也可以不删除)字符而不改变剩余字符的相对位置形成的新字符串。(例如,"ACE""ABCDE" 的一个子序列,而 "AEC" 不是)。

示例:

输入:s = “rabbbit”, t = “rabbit”
输出:3

解释:有 3 种方法可以生成 “rabbit” 的子序列。

难度分析

这道题目是一个动态规划问题,属于中等偏上难度。

解题算法

方法一:动态规划
解题步骤
  1. 初始化一个 (m+1)x(n+1) 的二维数组 dp,其中 mn 分别是字符串 st 的长度。dp[i][j] 表示 s 的前 i 个字符中包含 t 的前 j 个字符的子序列个数。
  2. 设定初始条件:当 j=0,即 t 为空字符串时,dp[i][0] 都为 1
  3. 遍历字符串 st,更新 dp 表:
    • 如果 s[i-1] == t[j-1],则 dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
    • 否则,dp[i][j] = dp[i-1][j]
  4. 返回 dp[m][n]
Python 示例
def numDistinct(s: str, t: str) -> int:
    m, n = len(s), len(t)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    for i in range(m + 1):
        dp[i][0] = 1  # 任何字符串包含空字符串的子序列有一个,即空序列

    for i in range(1, m + 1):
        for j in range(1, n + 1):
            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[m][n]
方法二:记忆化递归(优化的 DFS)
解题步骤
  1. 使用递归函数 dfs(i, j) 来表示从 s[i:]t[j:] 开始的子序列匹配个数。
  2. 如果 j == len(t),表示 t 已经被完全匹配,返回 1
  3. 如果 i == len(s)j != len(t),则无法匹配,返回 0
  4. 使用一个记忆化数组 memo 来存储已计算的结果,避免重复计算。
  5. 递归计算两种情况:选择当前 s[i] 或者跳过当前 s[i]
Python 示例
def numDistinct(s: str, t: str) -> int:
    memo = {}

    def dfs(i, j):
        if j == len(t):
            return 1
        if i == len(s):
            return 0
        if (i, j) in memo:
            return memo[(i, j)]

        if s[i] == t[j]:
            memo[(i, j)] = dfs(i + 1, j + 1) + dfs(i + 1, j)
        else:
            memo[(i, j)] = dfs(i + 1, j)
        return memo[(i, j)]

    return dfs(0, 0)
方法三:滚动数组优化的动态规划
Python 示例
def numDistinct(s: str, t: str) -> int:
    m, n = len(s), len(t)
    dp = [0] * (n + 1)
    dp[0] = 1  # 初始化dp数组,任何字符串都包含空字符串的子序列,即空序列本身

    for i in range(1, m + 1):
        # 从后向前遍历,防止覆盖需要的数据
        for j in range(n, 0, -1):
            if s[i - 1] == t[j - 1]:
                dp[j] += dp[j - 1]

    return dp[n]
算法分析

滚动数组技术可以减少动态规划的空间复杂度,只使用一维数组存储中间结果,大大减少了内存的使用。

方法四:空间优化的记忆化递归
解题步骤
  1. 类似于记忆化递归,使用一个一维数组 memo 来代替二维数组,减少空间复杂度。
  2. 根据 t 的长度来初始化 memo
  3. 使用递归方式填充 memo,每次计算后存储结果。
Python 示例
def numDistinct(s: str, t: str) -> int:
    n = len(t)
    memo = [-1] * (n + 1)

    def dfs(i, j):
        if j == n:
            return 1
        if i == len(s):
            return 0
        if memo[j] != -1:
            return memo[j]

        res = 0
        if s[i] == t[j]:
            res = dfs(i + 1, j + 1)
        res += dfs(i + 1, j)
        memo[j] = res
        return res

    return dfs(0, 0)
总结
  • 动态规划是解决此类问题的最直接方法,其时间和空间复杂度均较高。
  • 记忆化递归提供了更灵活的解决方案,适用于解决复杂递归问题,但可能会导致堆栈溢出。
  • 滚动数组空间优化的递归可以显著减少空间复杂度,适用于空间敏感的应用。
应用示例

在文本分析和自然语言处理中,计算字符串的子序列可以帮助理解文本的结构和语义。例如,在关键词匹配、信息检索和语言模型中,这些技术可以用来计算和优化大量文本数据。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是短信群发上行和下行

短信群发是一种广泛应用于商业和个人通信的技术,通过一次多条的方式,可以快速高效地传递信息。在实际的群发过程中,会涉及到上行和下行的概念。本文将详细介绍什么是短信群发上行和下行,并解释它们的应用。 什么是短信群发上行 群…

Dbeaver连接一段时间不操作后断开的问题

右键数据库连接点击编辑连接点击初始化将连接保持改成60s

BW4HANA混合建模 用ADSO的哪个视图?

写日志的ADSO除了1,2,3表之外。还会有6,7,8view。8view是上了BW4HANA2.0之后激活ADSO就会生成的。如果旧版本没有8,那就RSDG_ADSO_ACTIVATE激活一下。 如果勾了外部HANA视图,那就等于说还有一个HANA view。 首先咱知道ADSO是BW里面用来物理存储&#xf…

做一个属于自己的软件-pyside6快速上手教程

首先环境需要安装python3和pip,软件使用pycharm,安装也都很简单 首先需要安装pyside6,在终端执行: pip install pyside6 然后进入可视化编辑界面 pyside6-designer 进入后创建即可 可以从左侧点击鼠标拉组件进入到中间的工作区&#xff…

BLIP和BLIP2 论文讲解

文章目录 BLIPIntroductionMethod模型架构预训练目标字幕和过滤(Capfilt) BLIP2IntroductionMethod模型结构Q-Former预训练第一阶段Q-Former预训练第二阶段 BLIP 论文: 《BLIP: Bootstrapping Language-Image Pre-training for Unified Visio…

详解BOM编程

华子目录 BOM编程window对象常见的window对象的属性常见的window对象的方法注意 history对象history对象的属性history对象的方法 screen 对象navigator 对象属性方法 location对象属性方法示例 BOM编程 JavaScript本质是在浏览器中运行,所以JavaScript提供了BOM&a…

一文详解FDA邮件认证证书的重要性及其应用

随着全球化和电子商务的飞速发展,跨国贸易和沟通变得越来越频繁。在这个过程中,邮件作为重要的沟通工具,其安全性和可信度成为了各方关注的焦点。FDA(美国食品药品监督管理局)邮件认证证书就是在这一背景下应运而生的一…

1W 3KVDC 隔离 稳压单输出 DC/DC 电源模块——TPV-SAR 系列

TPV-SAR系列产品是专门针对PCB上分布式电源系统中需要与输入电源隔离且输出精度要求较高的电源应用场合而设计。该产品适用于;1)输入电源的电压变化≤5%;2)输入输出之前要求隔离电压≥3000VDC;3)对输出电压…

mac电脑如何安装java

1、检查当前系统的 Java 版本 打开终端,输入以下命令查看当前 Java 版本 /usr/bin/java -version 2、前往 Java 官网下载 Java JDK 打开 Java 官网 (https://www.java.com/zh-CN/download/) 并下载最新版本的 Java JDK。 3、安装 Java JDK 双击下载的 .dmg 文件启动安装程序…

【全开源】Java共享台信息共享系统源码

特色功能 信息整合与共享:该平台提供一站式信息整合服务,将各种类型的信息资源进行汇聚,方便用户快速查找和获取所需资源。多种共享功能:支持信息共享、共享车位、共享会议室、共享电动车等多种共享功能,提高资源利用…

Windows系统本地部署DrawDB数据库设计工具并实现无公网IP远程访问

文章目录 1. Windows本地部署DrawDB2. 安装Cpolar内网穿透3. 实现公网访问DrawDB4. 固定DrawDB公网地址 开发中很多时候都会使用到数据库,所以选择一个好用的数据库设计工具会让工作效率翻倍。在当今数字化时代,数据库管理是许多企业和个人项目的核心。设…

vue-fontawesome-elementui-icon-picker选择icon框架

第一步:安装vue-fontawesome-elementui-icon-picker依赖 npm install vue-fontawesome-elementui-icon-picker --save-dev 第二步:main.js配置 (放在element ui引入之后) import iconPicker from vue-fontawesome-elementui-icon-picker; Vue.use(ico…

Python-VBA函数之旅-setattr函数

目录 一、setattr函数的常见应用场景 二、setattr函数使用注意事项 三、如何用好setattr函数? 1、setattr函数: 1-1、Python: 1-2、VBA: 2、推荐阅读: 个人主页: https://blog.csdn.net/ygb_1024?…

笨方法自学python(六)

上一节中出现了\n,这个作用是换行。\后面带不同字符有不同的作用,我们先简单了解几个, 使用反斜杠 \ (back-slash) 可以将难打印出来的字符放到字符串。针对不同的符号有很多这样的所谓“转义序列(escape sequences)”,我们来练习…

OPC :快速上手

本系列为OPC技术的快速上以及持续研究和技术实战专栏,将不定期更新。 本章节提供OPC系列技术博文的快速导航。 《OPC服务器简介和入门介绍》 《物联网平台如何为OPC服务器创造新生命力》 《OPC服务器开发之WtOPCSvr——开发文档(1)》 《OPC服…

使用flutter开发一个U盘文件管理APP,只解析图片文件

今天教大家用flutter撸一个U盘文件管理APP,需求是这样的: 当我在Android设备上插入U盘后,我能在APP中打开U盘的文件目录,并且能进入对应目录的下一级目录,如果下级目录下有图片文件,我就对这个图片文件进行解析,并展示出来。 需求了解后,先上个效果图: 效果图看完后,…

海外媒体发稿:7个出口贸易媒体发稿推广必备技巧-华媒舍

在如今全球化的经济环境中,出口贸易在各个国家的经济中占据了重要地位。作为出口贸易从业者,我们都明白推广产品和品牌对于成功开拓国际市场至关重要。而在推广方面,媒体发稿则是一种常见而有效的方式。本文将分享7个出口贸易媒体发稿推广的必…

Spark云计算平台Databricks使用,创建workspace和Compute计算集群(Spark集群)

Databricks,是属于 Spark 的商业化公司,由美国加州大学伯克利 AMP 实验室的 Spark 大数据处理系统多位创始人联合创立。Databricks 致力于提供基于 Spark 的云服务,可用于数据集成,数据管道等任务。 1 创建workspace 点击创建wor…

STM32F4xx开发学习_USART串口通讯

USART串口通讯 USART简介 USART(universal synchronous asynchronous receiver transmitter),通用同步异步接收发射机,是一种全双工异步通信串行通讯方式,是STM32内部集成的硬件外设,以帧格式传输数据。搭…

泛微E9开发 通过点击按钮来复制选择的明细行

泛微E9开发 通过点击按钮来复制选择的明细行 复制明细行功能背景展示效果实现方法 复制明细行 功能背景 用户可以通过“复制明细”按钮来实现新增选择的明细行,并且新增明细行的数据跟选择的数据完全一样,具体操作如下图所示: 手动新增明细…
最新文章