题目详情

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

一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,“ACE” 是 “ABCDE” 的一个子序列,而 “AEC” 不是)

示例 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
^^^

题目详解

动态规划关键是找到递推公式, 而找到递推公式,首先就是要找到如何表示数组dp 然后找到递推关系。

我们可以发现。此题和编辑距离一样。都是由两个字符串, 是从一个字符串变到另一个字符串, 对于编辑距离这个题是在字符串1进行增, 删, 改操作变到字符串2, 此题是在字符串1里找到字符串2。

所以对于此题我们先构造dp, 类似于编辑距离, 定义dp[i][j],表示字符串1的从0开始长度为i的字符串, 和字符串2的从长度为j的字符串, 这两个字符串匹配的个数。

下面就是要找递推式了

首先开始可能递推看不出来, 所以有些做法就是写一个例子, 然后把例子的dp全部写出来, 这里就以题目的S = “rabbbit”, T = "rabbit"例子



观察到

  • 最终结果是dp[S.size()][T.size()]
  • 每当S[i] == T[j]时, dp[i][j]会增加, 比如S = rabb, T = rab. 此时dp[i][j] = dp[i][j-1] + x (x为增加量)
  • 当S[i] != T[j]时 dp[i][j] 会不变
  • x是什么呢?,对于例子S=rabbb, T=rabb, x为2, 而dp[i-1][j-1] = 2, 而且其他的例子也能推出来,所以可以假设x = dp[i-1][j-1]
  • 当计算dp[i][j]时, dp[i][j-1]是一定被包括进去的, 当两个字符串的最后一个字符相同时, 那么dp[i-1][j-1]也会包括进去

通过上面的分析, 我们已经找到了递推式子

dp[i][j] = dp[i][j-1] +  (s[i] == t[j]) ? dp[i-1][j-1] : 0

而且通过上面的例子 可以找到初始情况

dp[0][j] = 0;

dp[j][0] = 1; (包含空串)

dp[0][0] = 1 (防止第一个条件覆盖)

AC代码


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

LeetCode 115.不同的子序列 详解的更多相关文章

  1. Java实现 LeetCode 115 不同的子序列

    115. 不同的子序列 给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数. 一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字 ...

  2. LeetCode.516 最长回文子序列 详解

    题目详情 给定一个字符串s,找到其中最长的回文子序列.可以假设s的最大长度为1000. 示例 1: 输入: "bbbab" 输出: 4 一个可能的最长回文子序列为 "bb ...

  3. Leetcode 115.不同的子序列

    不同的子序列 给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数. 一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串.(例 ...

  4. leetcode 115不同的子序列

    滚动数组: /***** 下标从1开始 dp[i][j]:= numbers of subseq of S[1:j] equals T[1:i] if(s[j]==t[i]):(那么之后的子串可以是是 ...

  5. LeetCode 763划分字母区间 详解

    题目详情 字符串 S 由小写字母组成.我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段.返回一个表示每个字符串片段的长度的列表. 示例 1: 输入: S = "ab ...

  6. LeetCode(42.接雨水)多解法详解

    接雨水解法详解: 题目: 基本思路:从图上可以看出要想接住雨水,必须是凹字形的,也就是当前位置的左右两边必须存在高度大于它的地方,所以我们要想知道当前位置最多能存储多少水,只需找到左边最高处max_l ...

  7. [原创]mybatis详解说明

    mybatis详解 2017-01-05MyBatis之代理开发模式1 mybatis-Dao的代理开发模式 Dao:数据访问对象 原来:定义dao接口,在定义dao的实现类 dao的代理开发模式 只 ...

  8. 3.awk数组详解及企业实战案例

    awk数组详解及企业实战案例 3.打印数组: [root@nfs-server test]# awk 'BEGIN{array[1]="zhurui";array[2]=" ...

  9. linux查看端口及端口详解

    今天现场查看了TCP端口的占用情况,如下图   红色部分是IP,现场那边问我是不是我的程序占用了tcp的链接,,我远程登陆现场查看了一下,这种类型的tcp链接占用了400多个,,后边查了一下资料,说E ...

随机推荐

  1. P3379 最近公共祖先(LCA) 洛谷

    题意简单明了(这就是个模板). 就是让我们找2个节点的公共祖先而已,但我们要讲的做法不是生硬的爆搜,而且直接搜好像过不去…… 这次就讲我往后拖了n多天才开始学了倍增LCA. 嗯,这个题,如果2个节点的 ...

  2. 耐心看,1个Dubbo漏洞,35道必问面试题,Dubbo没什么可神秘的

    Dubbo漏洞 无意中在网上看到了这样的一条新闻,说是我们360监测发现了Dubbo官方发布的危险漏洞通告,而且尴尬的是,世界上受影响最大的居然是中国,有图有真相 我感觉这也从侧面证明了一件事情,就是 ...

  3. windows如何解决Error: Registry key 'Software\JavaSoft\Java Runtime Environment'\CurrentVersion'

    问题再现与解读 首次,使用 java 命令+任意参数 都会报这个错误,最典型的就是java -version 解读一下这个报错信息,注册表路径 Software\JavaSoft\Java Runti ...

  4. CSS3选择器用法小结

    1.*通配符选择器 eg:*{margin:0;padding:0;} 2.#id选择符 ID选择器是CSS中效率最高的选择器,使用的时候要保证ID的唯一性 eg:#div{width:960px;m ...

  5. Dockerfile镜像优化,减小镜像

    前言镜像的优化注意几条: 选择最精简的基础镜像减少镜像的层数清理镜像构建的中间产物注意优化网络请求尽量去用构建缓存使用多阶段构建镜像接下来我们以rhel7镜像构建容器,并在容器中安装nginx的源码包 ...

  6. Laragon修改配置快速创建其他框架的项目

    配置方式 依葫芦画瓢,如添加thinkPHP: # Thinkphp Thinkphp 3.2=composer create-project topthink/thinkphp %s Thinkph ...

  7. 3. 懂了这些,方敢在简历上说会用Jackson写JSON

    你必须非常努力,才能看起来毫不费力.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众 ...

  8. Python os.renames() 方法

    概述 os.renames() 方法用于递归重命名目录或文件.类似rename().高佣联盟 www.cgewang.com 语法 renames()方法语法格式如下: os.renames(old, ...

  9. Python time asctime()方法

    描述 Python time asctime() 函数接受时间元组并返回一个可读的形式为"Tue Dec 11 18:07:14 2008"(2008年12月11日 周二18时07 ...

  10. PHP str_shuffle() 函数

    实例 随机地打乱字符串中的所有字符: <?php高佣联盟 www.cgewang.comecho str_shuffle("Hello World");?> 定义和用法 ...