@@ -33,6 +33,8 @@ s 和 t 由英文字母组成
33
33
34
34
dp[ i] [ j ] :以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[ i] [ j ] 。
35
35
36
+ 为什么i-1,j-1 这么定义我在 [ 718. 最长重复子数组] ( https://programmercarl.com/0718.最长重复子数组.html ) 中做了详细的讲解。
37
+
36
38
2 . 确定递推公式
37
39
38
40
这一类问题,基本是要分析两种情况
@@ -42,25 +44,31 @@ dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为d
42
44
43
45
当s[ i - 1] 与 t[ j - 1] 相等时,dp[ i] [ j ] 可以有两部分组成。
44
46
45
- 一部分是用s[ i - 1] 来匹配,那么个数为dp[ i - 1] [ j - 1 ] 。
47
+ 一部分是用s[ i - 1] 来匹配,那么个数为dp[ i - 1] [ j - 1 ] 。即不需要考虑当前s子串和t子串的最后一位字母,所以只需要 dp [ i-1 ] [ j-1 ] 。
46
48
47
49
一部分是不用s[ i - 1] 来匹配,个数为dp[ i - 1] [ j ] 。
48
50
49
- 这里可能有同学不明白了 ,为什么还要考虑 不用s[ i - 1] 来匹配,都相同了指定要匹配啊。
51
+ ** 这里可能有录友不明白了 ,为什么还要考虑 不用s[ i - 1] 来匹配,都相同了指定要匹配啊** 。
50
52
51
53
例如: s:bagg 和 t:bag ,s[ 3] 和 t[ 2] 是相同的,但是字符串s也可以不用s[ 3] 来匹配,即用s[ 0] s[ 1] s[ 2] 组成的bag。
52
54
53
55
当然也可以用s[ 3] 来匹配,即:s[ 0] s[ 1] s[ 3] 组成的bag。
54
56
55
57
所以当s[ i - 1] 与 t[ j - 1] 相等时,dp[ i] [ j ] = dp[ i - 1] [ j - 1 ] + dp[ i - 1] [ j ] ;
56
58
57
- 当s[ i - 1] 与 t[ j - 1] 不相等时,dp[ i] [ j ] 只有一部分组成,不用s[ i - 1] 来匹配,即:dp[ i - 1] [ j ]
59
+ 当s[ i - 1] 与 t[ j - 1] 不相等时,dp[ i] [ j ] 只有一部分组成,不用s[ i - 1] 来匹配(就是模拟在s中删除这个元素) ,即:dp[ i - 1] [ j ]
58
60
59
61
所以递推公式为:dp[ i] [ j ] = dp[ i - 1] [ j ] ;
60
62
63
+ 这里可能有录友还疑惑,为什么只考虑 “不用s[ i - 1] 来匹配” 这种情况, 不考虑 “不用t[ j - 1] 来匹配” 的情况呢。
64
+
65
+ 这里大家要明确,我们求的是 s 中有多少个 t,而不是 求t中有多少个s,所以只考虑 s中删除元素的情况,即 不用s[ i - 1] 来匹配 的情况。
66
+
61
67
3 . dp数组如何初始化
62
68
63
- 从递推公式dp[ i] [ j ] = dp[ i - 1] [ j - 1 ] + dp[ i - 1] [ j ] ; 和 dp[ i] [ j ] = dp[ i - 1] [ j ] ; 中可以看出dp[ i] [ 0 ] 和dp[ 0] [ j ] 是一定要初始化的。
69
+ 从递推公式dp[ i] [ j ] = dp[ i - 1] [ j - 1 ] + dp[ i - 1] [ j ] ; 和 dp[ i] [ j ] = dp[ i - 1] [ j ] ; 中可以看出dp[ i] [ j ] 是从上方和左上方推导而来,如图:,那么 dp[ i] [ 0 ] 和dp[ 0] [ j ] 是一定要初始化的。
70
+
71
+ ![ ] ( https://code-thinking-1253855093.file.myqcloud.com/pics/20221222165412.png )
64
72
65
73
每次当初始化的时候,都要回顾一下dp[ i] [ j ] 的定义,不要凭感觉初始化。
66
74
@@ -91,6 +99,8 @@ for (int j = 1; j <= t.size(); j++) dp[0][j] = 0; // 其实这行代码可以和
91
99
92
100
从递推公式dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]; 和 dp[i][j] = dp[i - 1][j]; 中可以看出dp[i][j]都是根据左上方和正上方推出来的。
93
101
102
+ 
103
+
94
104
所以遍历的时候一定是从上到下,从左到右,这样保证dp[i][j]可以根据之前计算出来的数值进行计算。
95
105
96
106
代码如下:
0 commit comments