Skip to content

Commit 9e3e2fe

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 78ef0fa commit 9e3e2fe

File tree

6 files changed

+400
-2
lines changed

6 files changed

+400
-2
lines changed

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

Lines changed: 147 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,22 +81,168 @@
8181

8282
<!-- 这里可写通用的实现逻辑 -->
8383

84+
**方法一:预处理 + 记忆化搜索**
85+
86+
我们注意到,字符串数组 $words$ 中的每一个字符串长度都相同,不妨记为 $n$,那么我们可以预处理出一个二维数组 $cnt$,其中 $cnt[j][c]$ 表示字符串数组 $words$ 中第 $j$ 个位置的字符 $c$ 的数量。
87+
88+
接下来,我们设计一个函数 $dfs(i, j)$,表示构造 $target[i,..]$ 且当前从 $words$ 中选取的字符位置为 $j$ 的方案数。那么答案就是 $dfs(0, 0)$。
89+
90+
函数 $dfs(i, j)$ 的计算逻辑如下:
91+
92+
- 如果 $i \geq m$,说明 $target$ 中的所有字符都已经被选取,那么方案数为 $1$。
93+
- 如果 $j \geq n$,说明 $words$ 中的所有字符都已经被选取,那么方案数为 $0$。
94+
- 否则,我们可以不选择 $words$ 中的第 $j$ 个位置的字符,那么方案数为 $dfs(i, j + 1)$;或者我们选择 $words$ 中的第 $j$ 个位置的字符,那么方案数为 $dfs(i + 1, j + 1) \times cnt[j][target[i] - 'a']$。
95+
96+
最后,我们返回 $dfs(0, 0)$ 即可。注意答案的取模操作。
97+
98+
时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 为字符串 $target$ 的长度,而 $n$ 为字符串数组 $words$ 中每个字符串的长度。
99+
84100
<!-- tabs:start -->
85101

86102
### **Python3**
87103

88104
<!-- 这里可写当前语言的特殊实现逻辑 -->
89105

90106
```python
91-
107+
class Solution:
108+
def numWays(self, words: List[str], target: str) -> int:
109+
@cache
110+
def dfs(i, j):
111+
if i >= m:
112+
return 1
113+
if j >= n:
114+
return 0
115+
ans = dfs(i, j + 1) + dfs(i + 1, j + 1) * cnt[j][ord(target[i]) - ord("a")]
116+
ans %= mod
117+
return ans
118+
119+
m = len(target)
120+
n = len(words[0])
121+
cnt = [[0] * 26 for _ in range(n)]
122+
for w in words:
123+
for j, c in enumerate(w):
124+
cnt[j][ord(c) - ord("a")] += 1
125+
mod = 10**9 + 7
126+
return dfs(0, 0)
92127
```
93128

94129
### **Java**
95130

96131
<!-- 这里可写当前语言的特殊实现逻辑 -->
97132

98133
```java
134+
class Solution {
135+
private int m;
136+
private int n;
137+
private String target;
138+
private Integer[][] f;
139+
private int[][] cnt;
140+
private final int mod = (int) 1e9 + 7;
141+
142+
public int numWays(String[] words, String target) {
143+
m = target.length();
144+
n = words[0].length();
145+
f = new Integer[m][n];
146+
this.target = target;
147+
cnt = new int[n][26];
148+
for (var w : words) {
149+
for (int j = 0; j < n; ++j) {
150+
cnt[j][w.charAt(j) - 'a']++;
151+
}
152+
}
153+
return dfs(0, 0);
154+
}
155+
156+
private int dfs(int i, int j) {
157+
if (i >= m) {
158+
return 1;
159+
}
160+
if (j >= n) {
161+
return 0;
162+
}
163+
if (f[i][j] != null) {
164+
return f[i][j];
165+
}
166+
long ans = dfs(i, j + 1);
167+
ans += 1L * dfs(i + 1, j + 1) * cnt[j][target.charAt(i) - 'a'];
168+
ans %= mod;
169+
return f[i][j] = (int) ans;
170+
}
171+
}
172+
```
173+
174+
### **C++**
175+
176+
```cpp
177+
class Solution {
178+
public:
179+
int numWays(vector<string>& words, string target) {
180+
const int mod = 1e9 + 7;
181+
int m = target.size(), n = words[0].size();
182+
vector<vector<int>> cnt(n, vector<int>(26));
183+
for (auto& w : words) {
184+
for (int j = 0; j < n; ++j) {
185+
++cnt[j][w[j] - 'a'];
186+
}
187+
}
188+
int f[m][n];
189+
memset(f, -1, sizeof(f));
190+
function<int(int, int)> dfs = [&](int i, int j) -> int {
191+
if (i >= m) {
192+
return 1;
193+
}
194+
if (j >= n) {
195+
return 0;
196+
}
197+
if (f[i][j] != -1) {
198+
return f[i][j];
199+
}
200+
int ans = dfs(i, j + 1);
201+
ans = (ans + 1LL * dfs(i + 1, j + 1) * cnt[j][target[i] - 'a']) % mod;
202+
return f[i][j] = ans;
203+
};
204+
return dfs(0, 0);
205+
}
206+
};
207+
```
99208
209+
### **Go**
210+
211+
```go
212+
func numWays(words []string, target string) int {
213+
m, n := len(target), len(words[0])
214+
f := make([][]int, m)
215+
cnt := make([][26]int, n)
216+
for _, w := range words {
217+
for j, c := range w {
218+
cnt[j][c-'a']++
219+
}
220+
}
221+
for i := range f {
222+
f[i] = make([]int, n)
223+
for j := range f[i] {
224+
f[i][j] = -1
225+
}
226+
}
227+
const mod = 1e9 + 7
228+
var dfs func(i, j int) int
229+
dfs = func(i, j int) int {
230+
if i >= m {
231+
return 1
232+
}
233+
if j >= n {
234+
return 0
235+
}
236+
if f[i][j] != -1 {
237+
return f[i][j]
238+
}
239+
ans := dfs(i, j+1)
240+
ans = (ans + dfs(i+1, j+1)*cnt[j][target[i]-'a']) % mod
241+
f[i][j] = ans
242+
return ans
243+
}
244+
return dfs(0, 0)
245+
}
100246
```
101247

102248
### **...**

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

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,143 @@
6464
### **Python3**
6565

6666
```python
67-
67+
class Solution:
68+
def numWays(self, words: List[str], target: str) -> int:
69+
@cache
70+
def dfs(i, j):
71+
if i >= m:
72+
return 1
73+
if j >= n:
74+
return 0
75+
ans = dfs(i, j + 1) + dfs(i + 1, j + 1) * cnt[j][ord(target[i]) - ord("a")]
76+
ans %= mod
77+
return ans
78+
79+
m = len(target)
80+
n = len(words[0])
81+
cnt = [[0] * 26 for _ in range(n)]
82+
for w in words:
83+
for j, c in enumerate(w):
84+
cnt[j][ord(c) - ord("a")] += 1
85+
mod = 10**9 + 7
86+
return dfs(0, 0)
6887
```
6988

7089
### **Java**
7190

7291
```java
92+
class Solution {
93+
private int m;
94+
private int n;
95+
private String target;
96+
private Integer[][] f;
97+
private int[][] cnt;
98+
private final int mod = (int) 1e9 + 7;
99+
100+
public int numWays(String[] words, String target) {
101+
m = target.length();
102+
n = words[0].length();
103+
f = new Integer[m][n];
104+
this.target = target;
105+
cnt = new int[n][26];
106+
for (var w : words) {
107+
for (int j = 0; j < n; ++j) {
108+
cnt[j][w.charAt(j) - 'a']++;
109+
}
110+
}
111+
return dfs(0, 0);
112+
}
113+
114+
private int dfs(int i, int j) {
115+
if (i >= m) {
116+
return 1;
117+
}
118+
if (j >= n) {
119+
return 0;
120+
}
121+
if (f[i][j] != null) {
122+
return f[i][j];
123+
}
124+
long ans = dfs(i, j + 1);
125+
ans += 1L * dfs(i + 1, j + 1) * cnt[j][target.charAt(i) - 'a'];
126+
ans %= mod;
127+
return f[i][j] = (int) ans;
128+
}
129+
}
130+
```
131+
132+
### **C++**
133+
134+
```cpp
135+
class Solution {
136+
public:
137+
int numWays(vector<string>& words, string target) {
138+
const int mod = 1e9 + 7;
139+
int m = target.size(), n = words[0].size();
140+
vector<vector<int>> cnt(n, vector<int>(26));
141+
for (auto& w : words) {
142+
for (int j = 0; j < n; ++j) {
143+
++cnt[j][w[j] - 'a'];
144+
}
145+
}
146+
int f[m][n];
147+
memset(f, -1, sizeof(f));
148+
function<int(int, int)> dfs = [&](int i, int j) -> int {
149+
if (i >= m) {
150+
return 1;
151+
}
152+
if (j >= n) {
153+
return 0;
154+
}
155+
if (f[i][j] != -1) {
156+
return f[i][j];
157+
}
158+
int ans = dfs(i, j + 1);
159+
ans = (ans + 1LL * dfs(i + 1, j + 1) * cnt[j][target[i] - 'a']) % mod;
160+
return f[i][j] = ans;
161+
};
162+
return dfs(0, 0);
163+
}
164+
};
165+
```
73166
167+
### **Go**
168+
169+
```go
170+
func numWays(words []string, target string) int {
171+
m, n := len(target), len(words[0])
172+
f := make([][]int, m)
173+
cnt := make([][26]int, n)
174+
for _, w := range words {
175+
for j, c := range w {
176+
cnt[j][c-'a']++
177+
}
178+
}
179+
for i := range f {
180+
f[i] = make([]int, n)
181+
for j := range f[i] {
182+
f[i][j] = -1
183+
}
184+
}
185+
const mod = 1e9 + 7
186+
var dfs func(i, j int) int
187+
dfs = func(i, j int) int {
188+
if i >= m {
189+
return 1
190+
}
191+
if j >= n {
192+
return 0
193+
}
194+
if f[i][j] != -1 {
195+
return f[i][j]
196+
}
197+
ans := dfs(i, j+1)
198+
ans = (ans + dfs(i+1, j+1)*cnt[j][target[i]-'a']) % mod
199+
f[i][j] = ans
200+
return ans
201+
}
202+
return dfs(0, 0)
203+
}
74204
```
75205

76206
### **...**
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class Solution {
2+
public:
3+
int numWays(vector<string>& words, string target) {
4+
const int mod = 1e9 + 7;
5+
int m = target.size(), n = words[0].size();
6+
vector<vector<int>> cnt(n, vector<int>(26));
7+
for (auto& w : words) {
8+
for (int j = 0; j < n; ++j) {
9+
++cnt[j][w[j] - 'a'];
10+
}
11+
}
12+
int f[m][n];
13+
memset(f, -1, sizeof(f));
14+
function<int(int, int)> dfs = [&](int i, int j) -> int {
15+
if (i >= m) {
16+
return 1;
17+
}
18+
if (j >= n) {
19+
return 0;
20+
}
21+
if (f[i][j] != -1) {
22+
return f[i][j];
23+
}
24+
int ans = dfs(i, j + 1);
25+
ans = (ans + 1LL * dfs(i + 1, j + 1) * cnt[j][target[i] - 'a']) % mod;
26+
return f[i][j] = ans;
27+
};
28+
return dfs(0, 0);
29+
}
30+
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
func numWays(words []string, target string) int {
2+
m, n := len(target), len(words[0])
3+
f := make([][]int, m)
4+
cnt := make([][26]int, n)
5+
for _, w := range words {
6+
for j, c := range w {
7+
cnt[j][c-'a']++
8+
}
9+
}
10+
for i := range f {
11+
f[i] = make([]int, n)
12+
for j := range f[i] {
13+
f[i][j] = -1
14+
}
15+
}
16+
const mod = 1e9 + 7
17+
var dfs func(i, j int) int
18+
dfs = func(i, j int) int {
19+
if i >= m {
20+
return 1
21+
}
22+
if j >= n {
23+
return 0
24+
}
25+
if f[i][j] != -1 {
26+
return f[i][j]
27+
}
28+
ans := dfs(i, j+1)
29+
ans = (ans + dfs(i+1, j+1)*cnt[j][target[i]-'a']) % mod
30+
f[i][j] = ans
31+
return ans
32+
}
33+
return dfs(0, 0)
34+
}

0 commit comments

Comments
 (0)