C++实现LeetCode(115.不同的子序列)

 更新时间:2021年07月23日 15:24:04   作者:Grandyang  
这篇文章主要介绍了C++实现LeetCode(115.不同的子序列),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

[LeetCode] 115. Distinct Subsequences 不同的子序列

Given a string S and a string T, count the number of distinct subsequences of S which equals T.

A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).

Example 1:

Input: S =

"rabbbit"

, T =

"rabbit"
Output: 3

Explanation:

As shown below, there are 3 ways you can generate "rabbit" from S.
(The caret symbol ^ means the chosen letters)

rabbbit

^^^^ ^^

rabbbit

^^ ^^^^

rabbbit

^^^ ^^^

Example 2:

Input: S =

"babgbag"

, T =

"bag"
Output: 5

Explanation:

As shown below, there are 5 ways you can generate "bag" from S.
(The caret symbol ^ means the chosen letters)

babgbag

^^ ^

babgbag

^^    ^

babgbag

^    ^^

babgbag

  ^  ^^

babgbag

    ^^^

看到有关字符串的子序列或者配准类的问题,首先应该考虑的就是用动态规划 Dynamic Programming 来求解,这个应成为条件反射。而所有 DP 问题的核心就是找出状态转移方程,想这道题就是递推一个二维的 dp 数组,其中 dp[i][j] 表示s中范围是 [0, i] 的子串中能组成t中范围是 [0, j] 的子串的子序列的个数。下面我们从题目中给的例子来分析,这个二维 dp 数组应为:

  Ø r a b b b i t
Ø
1 1 1 1 1 1 1 1
r
0 1 1 1 1 1 1 1
a
0 0 1 1 1 1 1 1
b
0 0 0 1 2 3 3 3
b
0 0 0 0 1 3 3 3
i
0 0 0 0 0 0 3 3
t
0 0 0 0 0 0 0 3

首先,若原字符串和子序列都为空时,返回1,因为空串也是空串的一个子序列。若原字符串不为空,而子序列为空,也返回1,因为空串也是任意字符串的一个子序列。而当原字符串为空,子序列不为空时,返回0,因为非空字符串不能当空字符串的子序列。理清这些,二维数组 dp 的边缘便可以初始化了,下面只要找出状态转移方程,就可以更新整个 dp 数组了。我们通过观察上面的二维数组可以发现,当更新到 dp[i][j] 时,dp[i][j] >= dp[i][j - 1] 总是成立,再进一步观察发现,当 T[i - 1] == S[j - 1] 时,dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1],若不等, dp[i][j] = dp[i][j - 1],所以,综合以上,递推式为:

dp[i][j] = dp[i][j - 1] + (T[i - 1] == S[j - 1] ? dp[i - 1][j - 1] : 0)

根据以上分析,可以写出代码如下:

class Solution {
public:
    int numDistinct(string s, string t) {
        int m = s.size(), n = t.size();
        vector<vector<long>> dp(n + 1, vector<long>(m + 1));
        for (int j = 0; j <= m; ++j) dp[0][j] = 1;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                dp[i][j] = dp[i][j - 1] + (t[i - 1] == s[j - 1] ? dp[i - 1][j - 1] : 0);
            }
        }
        return dp[n][m];
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/115

参考资料:

https://leetcode.com/problems/distinct-subsequences/

https://leetcode.com/problems/distinct-subsequences/discuss/37327/Easy-to-understand-DP-in-Java

https://leetcode.com/problems/distinct-subsequences/discuss/37412/Any-better-solution-that-takes-less-than-O(n2)-space-while-in-O(n2)-time

到此这篇关于C++实现LeetCode(115.不同的子序列)的文章就介绍到这了,更多相关C++实现不同的子序列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现的O(n)复杂度内查找第K大数算法示例

    C++实现的O(n)复杂度内查找第K大数算法示例

    这篇文章主要介绍了C++实现的O(n)复杂度内查找第K大数算法,结合实例形式分析了算法的原理以及具体实现方法,需要的朋友可以参考下
    2017-08-08
  • C++中string与int的相互转换实现代码

    C++中string与int的相互转换实现代码

    这篇文章主要介绍了C++中string与int的相互转换实现代码,需要的朋友可以参考下
    2017-05-05
  • C++实现动态规划过程详解

    C++实现动态规划过程详解

    动态规划是解决一类最优问题的常用方法,它是解决最优化问题的一种途径,在本文中,我们将讨论如何使用C++实现动态规划算法,并提供一些示例来帮助您更好地理解该算法
    2023-05-05
  • 用C语言实现扫雷小程序

    用C语言实现扫雷小程序

    这篇文章主要为大家详细介绍了用C语言实现扫雷小程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C/C++中抽象类详解及其作用介绍

    C/C++中抽象类详解及其作用介绍

    这篇文章主要介绍了C/C++中抽象类详解及其作用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • C/C++实现segy文件的读取详解

    C/C++实现segy文件的读取详解

    SEGY是地震数据一般以地震道为单位进行组织,采用SEG-Y文件格式存储。标准SEGY文件一般包括三部分:卷头、道头与地震道数据。本文将介绍利用C++读取segy文件的方法,感兴趣的可以了解一下
    2022-03-03
  • C语言实现经典扫雷游戏流程

    C语言实现经典扫雷游戏流程

    扫雷是电脑上很经典的游戏,特意去网上玩了一会,几次调试之后,发现这个比三子棋要复杂一些,尤其是空白展开算法上和堵截玩家有的一拼,与实际游戏差别较大,不能使用光标,下面来详解每一步分析
    2021-11-11
  • C++获取特定进程CPU使用率的实现代码

    C++获取特定进程CPU使用率的实现代码

    写一个小程序在后台记录每个进程的CPU使用情况,揪出锁屏后占用CPU的进程,于是自己写了一个C++类CPUusage,方便地监视不同进程的CPU占用情况。本人编程还只是个新手,如有问题请多多指教
    2019-04-04
  • C++实现简易文本编辑器

    C++实现简易文本编辑器

    这篇文章主要为大家详细介绍了C++实现简易文本编辑器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • C++STL教程之vector模板的使用

    C++STL教程之vector模板的使用

    模板类vector是一个动态数组,类似于string类,可存放任意类型,能够末尾、中间增加数据,基本上是是new创建动态数组的替代品,vector可以自动完成new和delete
    2022-08-08

最新评论