Skip to content

Commit d5f4343

Browse files
committed
feat: add solutions to lc problem: No.1639
No.1639.Number of Ways to Form a Target String Given a Dictionary
1 parent b9e5cff commit d5f4343

File tree

4 files changed

+329
-18
lines changed

4 files changed

+329
-18
lines changed

solution/1600-1699/1639.Number of Ways to Form a Target String Given a Dictionary/README.md

+142-6
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@
9797

9898
时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 为字符串 $target$ 的长度,而 $n$ 为字符串数组 $words$ 中每个字符串的长度。
9999

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+
100112
<!-- tabs:start -->
101113

102114
### **Python3**
@@ -107,25 +119,42 @@
107119
class Solution:
108120
def numWays(self, words: List[str], target: str) -> int:
109121
@cache
110-
def dfs(i, j):
122+
def dfs(i: int, j: int) -> int:
111123
if i >= m:
112124
return 1
113125
if j >= n:
114126
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
117129
return ans
118130

119-
m = len(target)
120-
n = len(words[0])
131+
m, n = len(target), len(words[0])
121132
cnt = [[0] * 26 for _ in range(n)]
122133
for w in words:
123134
for j, c in enumerate(w):
124-
cnt[j][ord(c) - ord("a")] += 1
135+
cnt[j][ord(c) - ord('a')] += 1
125136
mod = 10**9 + 7
126137
return dfs(0, 0)
127138
```
128139

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+
129158
### **Java**
130159

131160
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -171,6 +200,31 @@ class Solution {
171200
}
172201
```
173202

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+
174228
### **C++**
175229

176230
```cpp
@@ -206,6 +260,32 @@ public:
206260
};
207261
```
208262
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+
209289
### **Go**
210290

211291
```go
@@ -245,6 +325,62 @@ func numWays(words []string, target string) int {
245325
}
246326
```
247327

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+
248384
### **...**
249385

250386
```

0 commit comments

Comments
 (0)