|
97 | 97 |
|
98 | 98 | 时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 为字符串 $target$ 的长度,而 $n$ 为字符串数组 $words$ 中每个字符串的长度。
|
99 | 99 |
|
| 100 | +**方法二:预处理 + 动态规划** |
| 101 | + |
| 102 | +与方法一类似,我们可以先预处理出一个二维数组 $cnt$,其中 $cnt[j][c]$ 表示字符串数组 $words$ 中第 $j$ 个位置的字符 $c$ 的数量。 |
| 103 | + |
| 104 | +接下来,我们定义 $f[i][j]$ 表示构造 $target$ 的前 $i$ 个字符,且当前是从 $words$ 中每个单词的前 $j$ 个字符中选取字符的方案数。那么答案就是 $f[m][n]$。初始时 $f[0][j] = 1$,其中 $0 \leq j \leq n$。 |
| 105 | + |
| 106 | +考虑 $f[i][j]$,其中 $i \gt 0$, $j \gt 0$。我们可以不选取 $words$ 中的第 $j$ 个位置的字符,那么方案数为 $f[i][j - 1]$;或者我们选择 $words$ 中的第 $j$ 个位置的字符,那么方案数为 $f[i - 1][j - 1] \times cnt[j - 1][target[i - 1] - 'a']$。最后,我们将这两种情况的方案数相加,即为 $f[i][j]$ 的值。 |
| 107 | + |
| 108 | +最后,我们返回 $f[m][n]$ 即可。注意答案的取模操作。 |
| 109 | + |
| 110 | +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 为字符串 $target$ 的长度,而 $n$ 为字符串数组 $words$ 中每个字符串的长度。 |
| 111 | + |
100 | 112 | <!-- tabs:start -->
|
101 | 113 |
|
102 | 114 | ### **Python3**
|
|
107 | 119 | class Solution:
|
108 | 120 | def numWays(self, words: List[str], target: str) -> int:
|
109 | 121 | @cache
|
110 |
| - def dfs(i, j): |
| 122 | + def dfs(i: int, j: int) -> int: |
111 | 123 | if i >= m:
|
112 | 124 | return 1
|
113 | 125 | if j >= n:
|
114 | 126 | return 0
|
115 |
| - ans = dfs(i, j + 1) + dfs(i + 1, j + 1) * cnt[j][ord(target[i]) - ord("a")] |
116 |
| - ans %= mod |
| 127 | + ans = dfs(i + 1, j + 1) * cnt[j][ord(target[i]) - ord('a')] |
| 128 | + ans = (ans + dfs(i, j + 1)) % mod |
117 | 129 | return ans
|
118 | 130 |
|
119 |
| - m = len(target) |
120 |
| - n = len(words[0]) |
| 131 | + m, n = len(target), len(words[0]) |
121 | 132 | cnt = [[0] * 26 for _ in range(n)]
|
122 | 133 | for w in words:
|
123 | 134 | for j, c in enumerate(w):
|
124 |
| - cnt[j][ord(c) - ord("a")] += 1 |
| 135 | + cnt[j][ord(c) - ord('a')] += 1 |
125 | 136 | mod = 10**9 + 7
|
126 | 137 | return dfs(0, 0)
|
127 | 138 | ```
|
128 | 139 |
|
| 140 | +```python |
| 141 | +class Solution: |
| 142 | + def numWays(self, words: List[str], target: str) -> int: |
| 143 | + m, n = len(target), len(words[0]) |
| 144 | + cnt = [[0] * 26 for _ in range(n)] |
| 145 | + for w in words: |
| 146 | + for j, c in enumerate(w): |
| 147 | + cnt[j][ord(c) - ord('a')] += 1 |
| 148 | + mod = 10**9 + 7 |
| 149 | + f = [[0] * (n + 1) for _ in range(m + 1)] |
| 150 | + f[0] = [1] * (n + 1) |
| 151 | + for i in range(1, m + 1): |
| 152 | + for j in range(1, n + 1): |
| 153 | + f[i][j] = f[i][j - 1] + f[i - 1][j - 1] * cnt[j - 1][ord(target[i - 1]) - ord('a')] |
| 154 | + f[i][j] %= mod |
| 155 | + return f[m][n] |
| 156 | +``` |
| 157 | + |
129 | 158 | ### **Java**
|
130 | 159 |
|
131 | 160 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
@@ -171,6 +200,31 @@ class Solution {
|
171 | 200 | }
|
172 | 201 | ```
|
173 | 202 |
|
| 203 | +```java |
| 204 | +class Solution { |
| 205 | + public int numWays(String[] words, String target) { |
| 206 | + int m = target.length(); |
| 207 | + int n = words[0].length(); |
| 208 | + final int mod = (int) 1e9 + 7; |
| 209 | + long[][] f = new long[m + 1][n + 1]; |
| 210 | + Arrays.fill(f[0], 1); |
| 211 | + int[][] cnt = new int[n][26]; |
| 212 | + for (var w : words) { |
| 213 | + for (int j = 0; j < n; ++j) { |
| 214 | + cnt[j][w.charAt(j) - 'a']++; |
| 215 | + } |
| 216 | + } |
| 217 | + for (int i = 1; i <= m; ++i) { |
| 218 | + for (int j = 1; j <= n; ++j) { |
| 219 | + f[i][j] = f[i][j - 1] + f[i - 1][j - 1] * cnt[j - 1][target.charAt(i - 1) - 'a']; |
| 220 | + f[i][j] %= mod; |
| 221 | + } |
| 222 | + } |
| 223 | + return (int) f[m][n]; |
| 224 | + } |
| 225 | +} |
| 226 | +``` |
| 227 | + |
174 | 228 | ### **C++**
|
175 | 229 |
|
176 | 230 | ```cpp
|
@@ -206,6 +260,32 @@ public:
|
206 | 260 | };
|
207 | 261 | ```
|
208 | 262 |
|
| 263 | +```cpp |
| 264 | +class Solution { |
| 265 | +public: |
| 266 | + int numWays(vector<string>& words, string target) { |
| 267 | + int m = target.size(), n = words[0].size(); |
| 268 | + const int mod = 1e9 + 7; |
| 269 | + long long f[m + 1][n + 1]; |
| 270 | + memset(f, 0, sizeof(f)); |
| 271 | + fill(f[0], f[0] + n + 1, 1); |
| 272 | + vector<vector<int>> cnt(n, vector<int>(26)); |
| 273 | + for (auto& w : words) { |
| 274 | + for (int j = 0; j < n; ++j) { |
| 275 | + ++cnt[j][w[j] - 'a']; |
| 276 | + } |
| 277 | + } |
| 278 | + for (int i = 1; i <= m; ++i) { |
| 279 | + for (int j = 1; j <= n; ++j) { |
| 280 | + f[i][j] = f[i][j - 1] + f[i - 1][j - 1] * cnt[j - 1][target[i - 1] - 'a']; |
| 281 | + f[i][j] %= mod; |
| 282 | + } |
| 283 | + } |
| 284 | + return f[m][n]; |
| 285 | + } |
| 286 | +}; |
| 287 | +``` |
| 288 | + |
209 | 289 | ### **Go**
|
210 | 290 |
|
211 | 291 | ```go
|
@@ -245,6 +325,62 @@ func numWays(words []string, target string) int {
|
245 | 325 | }
|
246 | 326 | ```
|
247 | 327 |
|
| 328 | +```go |
| 329 | +func numWays(words []string, target string) int { |
| 330 | + const mod = 1e9 + 7 |
| 331 | + m, n := len(target), len(words[0]) |
| 332 | + f := make([][]int, m+1) |
| 333 | + for i := range f { |
| 334 | + f[i] = make([]int, n+1) |
| 335 | + } |
| 336 | + for j := range f[0] { |
| 337 | + f[0][j] = 1 |
| 338 | + } |
| 339 | + cnt := make([][26]int, n) |
| 340 | + for _, w := range words { |
| 341 | + for j, c := range w { |
| 342 | + cnt[j][c-'a']++ |
| 343 | + } |
| 344 | + } |
| 345 | + for i := 1; i <= m; i++ { |
| 346 | + for j := 1; j <= n; j++ { |
| 347 | + f[i][j] = f[i][j-1] + f[i-1][j-1]*cnt[j-1][target[i-1]-'a'] |
| 348 | + f[i][j] %= mod |
| 349 | + } |
| 350 | + } |
| 351 | + return f[m][n] |
| 352 | +} |
| 353 | +``` |
| 354 | + |
| 355 | +### **TypeScript** |
| 356 | + |
| 357 | +```ts |
| 358 | +function numWays(words: string[], target: string): number { |
| 359 | + const m = target.length; |
| 360 | + const n = words[0].length; |
| 361 | + const f = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0)); |
| 362 | + const mod = 1e9 + 7; |
| 363 | + for (let j = 0; j <= n; ++j) { |
| 364 | + f[0][j] = 1; |
| 365 | + } |
| 366 | + const cnt = new Array(n).fill(0).map(() => new Array(26).fill(0)); |
| 367 | + for (const w of words) { |
| 368 | + for (let j = 0; j < n; ++j) { |
| 369 | + ++cnt[j][w.charCodeAt(j) - 97]; |
| 370 | + } |
| 371 | + } |
| 372 | + for (let i = 1; i <= m; ++i) { |
| 373 | + for (let j = 1; j <= n; ++j) { |
| 374 | + f[i][j] = |
| 375 | + f[i][j - 1] + |
| 376 | + f[i - 1][j - 1] * cnt[j - 1][target.charCodeAt(i - 1) - 97]; |
| 377 | + f[i][j] %= mod; |
| 378 | + } |
| 379 | + } |
| 380 | + return f[m][n]; |
| 381 | +} |
| 382 | +``` |
| 383 | + |
248 | 384 | ### **...**
|
249 | 385 |
|
250 | 386 | ```
|
|
0 commit comments