1. question: 不同的子序列(困难)
给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。
字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,”ACE” 是 “ABCDE” 的一个子序列,而 “AEC” 不是)
题目数据保证答案符合 32 位带符号整数范围。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/distinct-subsequences
示例 1:
1 | 输入:s = "rabbbit", t = "rabbit" |
示例 2:
1 | 输入:s = "babgbag", t = "bag" |
提示:
1 | 0 <= s.length, t.length <= 1000 |
2. answers
参考题解,这道题和判断子序列还是有区别的。判断子序列仅仅是判断是否是子序列,而本题除了判断是否是子序列之外,还要判断次数【这里的次数就是母串s可以找到多少个子序列,且子序列就是该子串t】。下面以一个小例子说明一下:
当判断“acbb”包含几个“acb”时,因为在遍历到各自的最后一个字符时,因为b=b,所以,acbb中最后一个b可以参加匹配,也可不参加匹配,【这里说的参加匹配,指的是是否匹配子串字符】,即出现了两种情况:
- 不参加匹配:“acb”包含几个“acb”,【因为不参加匹配,所以子串中完整无损】
- 参加匹配:“acb”包含几个“ac”,【因为参加匹配,所以子串中也要去掉匹配的字符】
显然“acbb”包含“acb”的子序列就是由上面两种情况总和组成,即1+1=2。同样上面的两种情况,也由该情况的子串组成。
当“acbb”中的b不等于“acb”中的b时,就类似上面的“acb”和“ac”比较,显然,因为“ac”是基准,所以只能是将b删掉,取决于“ac”包含了几个“ac”的情况。
本质上,因为要计算次数,所以同一个字符是否参与匹配就称为了关键。总体来看,和判断子序列类似,只不过定义的数组dp[i][j]不再表示子序列的长度,而是s[i]结尾的子串包含t[j]结尾的子串的子序列的个数。并且状态转移方程也不同。代码如下所示:
1 | public class Solution_0142 { |
3. 备注
参考力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 (leetcode-cn.com),代码随想录 (programmercarl.com)。