0115-不同的子序列
给你两个字符串 s
**** 和 t
,统计并返回在 s
的 子序列 中 t
出现的个数,结果需要对 109 + 7 取模。
示例 1:
**输入:** s = "rabbbit", t = "rabbit"
**输出** **:**3
**解释:**
如下所示, 有 3 种可以从 s 中得到 "rabbit" 的方案。
**_rabb_** b ** _it_**
**_ra_** b ** _bbit_**
**_rab_** b ** _bit_**
示例 2:
**输入:** s = "babgbag", t = "bag"
**输出** **:**5
**解释:**
如下所示, 有 5 种可以从 s 中得到 "bag" 的方案。
**_ba_** b _ **g**_ bag
**_ba_** bgba ** _g_**
_**b**_ abgb ** _ag_**
ba _ **b**_ gb _ **ag**_
babg ** _bag_**
提示:
1 <= s.length, t.length <= 1000
s
和t
由英文字母组成
方法一:动态规划
假设字符串 $s$ 和 $t$ 的长度分别为 $m$ 和 $n$。如果 $t$ 是 $s$ 的子序列,则 $s$ 的长度一定大于或等于 $t$ 的长度,即只有当 $m \ge n$ 时,$t$ 才可能是 $s$ 的子序列。如果 $m<n$,则 $t$ 一定不是 $s$ 的子序列,因此直接返回 $0$。
当 $m \ge n$ 时,可以通过动态规划的方法计算在 $s$ 的子序列中 $t$ 出现的个数。
创建二维数组 $\textit{dp}$,其中 $\textit{dp}[i][j]$ 表示在 $s[i:]$ 的子序列中 $t[j:]$ 出现的个数。
上述表示中,$s[i:]$ 表示 $s$ 从下标 $i$ 到末尾的子字符串,$t[j:]$ 表示 $t$ 从下标 $j$ 到末尾的子字符串。
考虑动态规划的边界情况:
当 $j=n$ 时,$t[j:]$ 为空字符串,由于空字符串是任何字符串的子序列,因此对任意 $0 \le i \le m$,有 $\textit{dp}[i][n]=1$;
当 $i=m$ 且 $j<n$ 时,$s[i:]$ 为空字符串,$t[j:]$ 为非空字符串,由于非空字符串不是空字符串的子序列,因此对任意 $0 \le j<n$,有 $\textit{dp}[m][j]=0$。
当 $i<m$ 且 $j<n$ 时,考虑 $\textit{dp}[i][j]$ 的计算:
当 $s[i]=t[j]$ 时,$\textit{dp}[i][j]$ 由两部分组成:
如果 $s[i]$ 和 $t[j]$ 匹配,则考虑 $t[j+1:]$ 作为 $s[i+1:]$ 的子序列,子序列数为 $\textit{dp}[i+1][j+1]$;
如果 $s[i]$ 不和 $t[j]$ 匹配,则考虑 $t[j:]$ 作为 $s[i+1:]$ 的子序列,子序列数为 $\textit{dp}[i+1][j]$。
因此当 $s[i]=t[j]$ 时,有 $\textit{dp}[i][j]=\textit{dp}[i+1][j+1]+\textit{dp}[i+1][j]$。
当 $s[i] \ne t[j]$ 时,$s[i]$ 不能和 $t[j]$ 匹配,因此只考虑 $t[j:]$ 作为 $s[i+1:]$ 的子序列,子序列数为 $\textit{dp}[i+1][j]$。
因此当 $s[i] \ne t[j]$ 时,有 $\textit{dp}[i][j]=\textit{dp}[i+1][j]$。
由此可以得到如下状态转移方程:
$$
\textit{dp}[i][j] = \begin{cases}
\textit{dp}[i+1][j+1]+\textit{dp}[i+1][j], & s[i]=t[j]\
\textit{dp}[i+1][j], & s[i] \ne t[j]
\end{cases}
$$
最终计算得到 $\textit{dp}[0][0]$ 即为在 $s$ 的子序列中 $t$ 出现的个数。
<,,,,,,,,,,,,,,,,,,,,,,,>
1 | class Solution { |
1 | var numDistinct = function(s, t) { |
1 | func numDistinct(s, t string) int { |
1 | class Solution: |
1 | class Solution { |
1 | int numDistinct(char* s, char* t) { |
复杂度分析
时间复杂度:$O(mn)$,其中 $m$ 和 $n$ 分别是字符串 $s$ 和 $t$ 的长度。二维数组 $\textit{dp}$ 有 $m+1$ 行和 $n+1$ 列,需要对 $\textit{dp}$ 中的每个元素进行计算。
空间复杂度:$O(mn)$,其中 $m$ 和 $n$ 分别是字符串 $s$ 和 $t$ 的长度。创建了 $m+1$ 行 $n+1$ 列的二维数组 $\textit{dp}$。