115. 不同的子序列
难度困难390收藏分享切换为英文接收动态反馈
给定一个字符串 s
和一个字符串 t
,计算在 s
的子序列中 t
出现的个数。
字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE"
是 "ABCDE"
的一个子序列,而 "AEC"
不是)
题目数据保证答案符合 32 位带符号整数范围。
示例 1:
1 | 输入:s = "rabbbit", t = "rabbit" |
示例 2:
1 | 输入:s = "babgbag", t = "bag" |
提示:
0 <= s.length, t.length <= 1000
s
和t
由英文字母组成
动态规划
s
的长度为m
,t
的长度为n
dp[i][j]
代表从j
到n
的字串在从i
到m
的字符串中有几个
$dp[i][j]=\left{\begin{array}{ll}
dp[i+1][j+1]+d p[i+1][j], & s[i]=t[j] \
dp[i+1][j], & s[i] \neq t[j]
\end{array}\right.$
1 | class Solution { |
动态规划
1 | class Solution { |
动态规划
1: 为啥状态方程这样对? 2:怎么想到这样的状态方程?
我个人习惯dp[i][j]
表示为s[0-i]
和t[0-j]
均闭区间的子序列个数,但这样不能表示s
和t
空串的情况
所以声明int[][] dp = new int[m + 1][n + 1];
这样dp[0][x]
可以表示s
为空串,dp[x][0]
同理。
先不扣初始化的细节,假设dp[i][j]
就是s[i]
和t[j]
索引的元素子序列数量
1:为啥状态方程是:
s[i] == t[j] 时 dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
s[i] != t[j] 时 dp[i][j] = dp[i-1][j]
先看s[i] == t[j]
时,以s = "rara" t = "ra"
为例,当i = 3, j = 1时,s[i] == t[j]。
此时分为2
种情况,s
串用最后一位的a
+ 不用最后一位的a
。
如果用s
串最后一位的a
,那么t
串最后一位的a
也被消耗掉,此时的子序列其实=dp[i-1][j-1]
如果不用s
串最后一位的a
,那就得看"rar"
里面是否有"ra"
子序列的了,就是dp[i-1][j]
所以dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
再看s[i] != t[j]
比如s = "rarb" t = "ra"
还是当i = 3, j = 1时,s[i] != t[j]
此时显然最后的b
想用也用不上啊。所以只能指望前面的"rar"
里面是否有能匹配"ra"
的
所以此时dp[i][j] = dp[i-1][j]
2: 怎么想到这样状态方程的?
一点个人经验,见过的很多2个串的题,大部分都是dp[i][j]
分别表示s
串[0...i]
和t
串[0...j]
怎么怎么样 然后都是观察s[i]和t[j]
分等或者不等的情况 而且方程通常就是 dp[i-1][j-1]
要么+ 要么 || dp[i-1][j]
类似的
1 | class Solution { |
参考引用文献