54
54
55
55
<!-- 这里可写通用的实现逻辑 -->
56
56
57
- 动态规划,` dp[i][j] ` 表示 ` s[:i] ` 的子序列中 ` t[:j] ` 的出现次数
57
+ ** 方法一:动态规划**
58
+
59
+ 我们定义 $f[ i] [ j ] $ 表示字符串 $s$ 的前 $i$ 个字符中,子序列构成字符串 $t$ 的前 $j$ 个字符的方案数。初始时 $f[ i] [ 0 ] =1$,其中 $i \in [ 0,m] $。
60
+
61
+ 当 $i \gt 0$ 时,考虑 $f[ i] [ j ] $ 的计算:
62
+
63
+ - 当 $s[ i-1] \ne t[ j-1] $ 时,不能选取 $s[ i-1] $,因此 $f[ i] [ j ] =f[ i-1] [ j ] $;
64
+ - 否则,可以选取 $s[ i-1] $,此时 $f[ i] [ j ] =f[ i-1] [ j-1 ] $。
65
+
66
+ 因此我们有如下的状态转移方程:
67
+
68
+ $$
69
+ f[i][j]=\left\{
70
+ \begin{aligned}
71
+ &f[i-1][j], &s[i-1] \ne t[j-1] \\
72
+ &f[i-1][j-1]+f[i-1][j], &s[i-1]=t[j-1]
73
+ \end{aligned}
74
+ \right.
75
+ $$
76
+
77
+ 最终的答案即为 $f[ m] [ n ] $,其中 $m$ 和 $n$ 分别是字符串 $s$ 和 $t$ 的长度。
78
+
79
+ 时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。
80
+
81
+ 我们注意到 $f[ i] [ j ] $ 的计算只和 $f[ i-1] [ .. ] $ 有关,因此,我们可以优化掉第一维,这样空间复杂度可以降低到 $O(n)$。
58
82
59
83
<!-- tabs:start -->
60
84
66
90
class Solution :
67
91
def numDistinct (self , s : str , t : str ) -> int :
68
92
m, n = len (s), len (t)
69
- dp = [[0 ] * (n + 1 ) for _ in range (m + 1 )]
93
+ f = [[0 ] * (n + 1 ) for _ in range (m + 1 )]
70
94
for i in range (m + 1 ):
71
- dp[i][0 ] = 1
72
- for i in range (1 , m + 1 ):
73
- for j in range (1 , n + 1 ):
74
- dp[i][j] = dp[i - 1 ][j]
75
- if s[i - 1 ] == t[j - 1 ]:
76
- dp[i][j] += dp[i - 1 ][j - 1 ]
77
- return dp[m][n]
95
+ f[i][0 ] = 1
96
+ for i, a in enumerate (s, 1 ):
97
+ for j, b in enumerate (t, 1 ):
98
+ f[i][j] = f[i - 1 ][j]
99
+ if a == b:
100
+ f[i][j] += f[i - 1 ][j - 1 ]
101
+ return f[m][n]
102
+ ```
103
+
104
+ ``` python
105
+ class Solution :
106
+ def numDistinct (self , s : str , t : str ) -> int :
107
+ n = len (t)
108
+ f = [1 ] + [0 ] * n
109
+ for a in s:
110
+ for j in range (n, 0 , - 1 ):
111
+ if a == t[j - 1 ]:
112
+ f[j] += f[j - 1 ]
113
+ return f[n]
78
114
```
79
115
80
116
### ** Java**
@@ -84,69 +120,168 @@ class Solution:
84
120
``` java
85
121
class Solution {
86
122
public int numDistinct (String s , String t ) {
87
- int m = s. length();
88
- int n = t. length();
89
- int [][] dp = new int [m + 1 ][n + 1 ];
90
- for (int i = 0 ; i <= m; i++ ) {
91
- dp[i][0 ] = 1 ;
123
+ int m = s. length(), n = t. length();
124
+ int [][] f = new int [m + 1 ][n + 1 ];
125
+ for (int i = 0 ; i < m + 1 ; ++ i) {
126
+ f[i][0 ] = 1 ;
92
127
}
93
- for (int i = 1 ; i <= m; i ++ ) {
94
- for (int j = 1 ; j <= n; j ++ ) {
95
- dp [i][j] = dp [i - 1 ][j];
128
+ for (int i = 1 ; i < m + 1 ; ++ i ) {
129
+ for (int j = 1 ; j < n + 1 ; ++ j ) {
130
+ f [i][j] = f [i - 1 ][j];
96
131
if (s. charAt(i - 1 ) == t. charAt(j - 1 )) {
97
- dp[i][j] += dp[i - 1 ][j - 1 ];
132
+ f[i][j] += f[i - 1 ][j - 1 ];
133
+ }
134
+ }
135
+ }
136
+ return f[m][n];
137
+ }
138
+ }
139
+ ```
140
+
141
+ ``` java
142
+ class Solution {
143
+ public int numDistinct (String s , String t ) {
144
+ int n = t. length();
145
+ int [] f = new int [n + 1 ];
146
+ f[0 ] = 1 ;
147
+ for (char a : s. toCharArray()) {
148
+ for (int j = n; j > 0 ; -- j) {
149
+ char b = t. charAt(j - 1 );
150
+ if (a == b) {
151
+ f[j] += f[j - 1 ];
98
152
}
99
153
}
100
154
}
101
- return dp[m] [n];
155
+ return f [n];
102
156
}
103
157
}
104
158
```
105
159
160
+ ### ** C++**
161
+
162
+ ``` cpp
163
+ class Solution {
164
+ public:
165
+ int numDistinct(string s, string t) {
166
+ int m = s.size(), n = t.size();
167
+ unsigned long long f[ m + 1] [ n + 1 ] ;
168
+ memset(f, 0, sizeof(f));
169
+ for (int i = 0; i < m + 1; ++i) {
170
+ f[ i] [ 0 ] = 1;
171
+ }
172
+ for (int i = 1; i < m + 1; ++i) {
173
+ for (int j = 1; j < n + 1; ++j) {
174
+ f[ i] [ j ] = f[ i - 1] [ j ] ;
175
+ if (s[ i - 1] == t[ j - 1] ) {
176
+ f[ i] [ j ] += f[ i - 1] [ j - 1 ] ;
177
+ }
178
+ }
179
+ }
180
+ return f[ m] [ n ] ;
181
+ }
182
+ };
183
+ ```
184
+
185
+ ```cpp
186
+ class Solution {
187
+ public:
188
+ int numDistinct(string s, string t) {
189
+ int n = t.size();
190
+ unsigned long long f[n + 1];
191
+ memset(f, 0, sizeof(f));
192
+ f[0] = 1;
193
+ for (char& a : s) {
194
+ for (int j = n; j; --j) {
195
+ char b = t[j - 1];
196
+ if (a == b) {
197
+ f[j] += f[j - 1];
198
+ }
199
+ }
200
+ }
201
+ return f[n];
202
+ }
203
+ };
204
+ ```
205
+
106
206
### ** Go**
107
207
108
208
``` go
109
209
func numDistinct (s string , t string ) int {
110
210
m , n := len (s), len (t)
111
- dp := make ([][]int , m+1 )
211
+ f := make ([][]int , m+1 )
212
+ for i := range f {
213
+ f[i] = make ([]int , n+1 )
214
+ }
112
215
for i := 0 ; i <= m; i++ {
113
- dp[i] = make ([]int , n+1 )
114
- dp[i][0 ] = 1
216
+ f[i][0 ] = 1
115
217
}
116
218
for i := 1 ; i <= m; i++ {
117
219
for j := 1 ; j <= n; j++ {
118
- dp [i][j] = dp [i-1 ][j]
220
+ f [i][j] = f [i-1 ][j]
119
221
if s[i-1 ] == t[j-1 ] {
120
- dp [i][j] += dp [i-1 ][j-1 ]
222
+ f [i][j] += f [i-1 ][j-1 ]
121
223
}
122
224
}
123
225
}
124
- return dp [m][n]
226
+ return f [m][n]
125
227
}
126
228
```
127
229
128
- ### ** C++**
230
+ ``` go
231
+ func numDistinct (s string , t string ) int {
232
+ n := len (t)
233
+ f := make ([]int , n+1 )
234
+ f[0 ] = 1
235
+ for _ , a := range s {
236
+ for j := n; j > 0 ; j-- {
237
+ if b := t[j-1 ]; byte (a) == b {
238
+ f[j] += f[j-1 ]
239
+ }
240
+ }
241
+ }
242
+ return f[n]
243
+ }
244
+ ```
129
245
130
- ``` cpp
131
- class Solution {
132
- public:
133
- int numDistinct(string s, string t) {
134
- int m = s.size(), n = t.size();
135
- vector<vector<unsigned long long >> dp(m + 1, vector<unsigned long long >(n + 1));
136
- for (int i = 0; i <= m; ++i) {
137
- dp[ i] [ 0 ] = 1;
246
+ ### ** TypeScript**
247
+
248
+ ``` ts
249
+ function numDistinct(s : string , t : string ): number {
250
+ const m = s .length ;
251
+ const n = t .length ;
252
+ const f: number [][] = new Array (m + 1 )
253
+ .fill (0 )
254
+ .map (() => new Array (n + 1 ).fill (0 ));
255
+ for (let i = 0 ; i <= m ; ++ i ) {
256
+ f [i ][0 ] = 1 ;
257
+ }
258
+ for (let i = 1 ; i <= m ; ++ i ) {
259
+ for (let j = 1 ; j <= n ; ++ j ) {
260
+ f [i ][j ] = f [i - 1 ][j ];
261
+ if (s [i - 1 ] === t [j - 1 ]) {
262
+ f [i ][j ] += f [i - 1 ][j - 1 ];
263
+ }
138
264
}
139
- for (int i = 1; i <= m; ++i) {
140
- for (int j = 1; j <= n; ++j) {
141
- dp[ i] [ j ] = dp[ i - 1] [ j ] ;
142
- if (s[ i - 1] == t[ j - 1] ) {
143
- dp[ i] [ j ] += dp[ i - 1] [ j - 1 ] ;
144
- }
265
+ }
266
+ return f [m ][n ];
267
+ }
268
+ ```
269
+
270
+ ``` ts
271
+ function numDistinct(s : string , t : string ): number {
272
+ const n = t .length ;
273
+ const f: number [] = new Array (n + 1 ).fill (0 );
274
+ f [0 ] = 1 ;
275
+ for (const a of s ) {
276
+ for (let j = n ; j ; -- j ) {
277
+ const b = t [j - 1 ];
278
+ if (a === b ) {
279
+ f [j ] += f [j - 1 ];
145
280
}
146
281
}
147
- return dp[ m] [ n ] ;
148
282
}
149
- };
283
+ return f [n ];
284
+ }
150
285
```
151
286
152
287
### ** ...**
0 commit comments