Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 36e6eb2

Browse files
authored
feat: add solutions to lc problem: No.3291 (doocs#3530)
No.3291.Minimum Number of Valid Strings to Form Target I
1 parent 81560c5 commit 36e6eb2

File tree

7 files changed

+741
-8
lines changed

7 files changed

+741
-8
lines changed

solution/3200-3299/3291.Minimum Number of Valid Strings to Form Target I/README.md

Lines changed: 253 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,32 +84,281 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3291.Mi
8484

8585
<!-- solution:start -->
8686

87-
### 方法一
87+
### 方法一:字典树 + 记忆化搜索
88+
89+
我们可以使用字典树存储所有有效字符串,然后使用记忆化搜索计算答案。
90+
91+
我们设计一个函数 $\textit{dfs}(i)$,表示从字符串 $\textit{target}$ 的第 $i$ 个字符开始,需要连接的最少字符串数量。那么答案就是 $\textit{dfs}(0)$。
92+
93+
函数 $\textit{dfs}(i)$ 的计算方式如下:
94+
95+
- 如果 $i \geq n$,表示字符串 $\textit{target}$ 已经遍历完了,返回 $0$;
96+
- 否则,我们可以从字典树中找到以 $\textit{target}[i]$ 开头的有效字符串,然后递归计算 $\textit{dfs}(i + \text{len}(w))$,其中 $w$ 是找到的有效字符串。我们取这些值中的最小值加 $1$ 作为 $\textit{dfs}(i)$ 的返回值。
97+
98+
为了避免重复计算,我们使用记忆化搜索。
99+
100+
时间复杂度 $O(n^2 + L)$,空间复杂度 $O(n + L)$。其中 $n$ 是字符串 $\textit{target}$ 的长度,而 $L$ 是所有有效字符串的总长度。
88101

89102
<!-- tabs:start -->
90103

91104
#### Python3
92105

93106
```python
94-
107+
def min(a: int, b: int) -> int:
108+
return a if a < b else b
109+
110+
111+
class Trie:
112+
def __init__(self):
113+
self.children: List[Optional[Trie]] = [None] * 26
114+
115+
def insert(self, w: str):
116+
node = self
117+
for i in map(lambda c: ord(c) - 97, w):
118+
if node.children[i] is None:
119+
node.children[i] = Trie()
120+
node = node.children[i]
121+
122+
123+
class Solution:
124+
def minValidStrings(self, words: List[str], target: str) -> int:
125+
@cache
126+
def dfs(i: int) -> int:
127+
if i >= n:
128+
return 0
129+
node = trie
130+
ans = inf
131+
for j in range(i, n):
132+
k = ord(target[j]) - 97
133+
if node.children[k] is None:
134+
break
135+
node = node.children[k]
136+
ans = min(ans, 1 + dfs(j + 1))
137+
return ans
138+
139+
trie = Trie()
140+
for w in words:
141+
trie.insert(w)
142+
n = len(target)
143+
ans = dfs(0)
144+
return ans if ans < inf else -1
95145
```
96146

97147
#### Java
98148

99149
```java
100-
150+
class Trie {
151+
Trie[] children = new Trie[26];
152+
153+
void insert(String w) {
154+
Trie node = this;
155+
for (int i = 0; i < w.length(); ++i) {
156+
int j = w.charAt(i) - 'a';
157+
if (node.children[j] == null) {
158+
node.children[j] = new Trie();
159+
}
160+
node = node.children[j];
161+
}
162+
}
163+
}
164+
165+
class Solution {
166+
private Integer[] f;
167+
private char[] s;
168+
private Trie trie;
169+
private final int inf = 1 << 30;
170+
171+
public int minValidStrings(String[] words, String target) {
172+
trie = new Trie();
173+
for (String w : words) {
174+
trie.insert(w);
175+
}
176+
s = target.toCharArray();
177+
f = new Integer[s.length];
178+
int ans = dfs(0);
179+
return ans < inf ? ans : -1;
180+
}
181+
182+
private int dfs(int i) {
183+
if (i >= s.length) {
184+
return 0;
185+
}
186+
if (f[i] != null) {
187+
return f[i];
188+
}
189+
Trie node = trie;
190+
f[i] = inf;
191+
for (int j = i; j < s.length; ++j) {
192+
int k = s[j] - 'a';
193+
if (node.children[k] == null) {
194+
break;
195+
}
196+
f[i] = Math.min(f[i], 1 + dfs(j + 1));
197+
node = node.children[k];
198+
}
199+
return f[i];
200+
}
201+
}
101202
```
102203

103204
#### C++
104205

105206
```cpp
106-
207+
class Trie {
208+
public:
209+
Trie* children[26]{};
210+
211+
void insert(string& word) {
212+
Trie* node = this;
213+
for (char& c : word) {
214+
int i = c - 'a';
215+
if (!node->children[i]) {
216+
node->children[i] = new Trie();
217+
}
218+
node = node->children[i];
219+
}
220+
}
221+
};
222+
223+
class Solution {
224+
public:
225+
int minValidStrings(vector<string>& words, string target) {
226+
int n = target.size();
227+
Trie* trie = new Trie();
228+
for (auto& w : words) {
229+
trie->insert(w);
230+
}
231+
const int inf = 1 << 30;
232+
int f[n];
233+
memset(f, -1, sizeof(f));
234+
auto dfs = [&](auto&& dfs, int i) -> int {
235+
if (i >= n) {
236+
return 0;
237+
}
238+
if (f[i] != -1) {
239+
return f[i];
240+
}
241+
f[i] = inf;
242+
Trie* node = trie;
243+
for (int j = i; j < n; ++j) {
244+
int k = target[j] - 'a';
245+
if (!node->children[k]) {
246+
break;
247+
}
248+
node = node->children[k];
249+
f[i] = min(f[i], 1 + dfs(dfs, j + 1));
250+
}
251+
return f[i];
252+
};
253+
int ans = dfs(dfs, 0);
254+
return ans < inf ? ans : -1;
255+
}
256+
};
107257
```
108258
109259
#### Go
110260
111261
```go
262+
type Trie struct {
263+
children [26]*Trie
264+
}
265+
266+
func (t *Trie) insert(word string) {
267+
node := t
268+
for _, c := range word {
269+
idx := c - 'a'
270+
if node.children[idx] == nil {
271+
node.children[idx] = &Trie{}
272+
}
273+
node = node.children[idx]
274+
}
275+
}
276+
277+
func minValidStrings(words []string, target string) int {
278+
n := len(target)
279+
trie := &Trie{}
280+
for _, w := range words {
281+
trie.insert(w)
282+
}
283+
const inf int = 1 << 30
284+
f := make([]int, n)
285+
var dfs func(int) int
286+
dfs = func(i int) int {
287+
if i >= n {
288+
return 0
289+
}
290+
if f[i] != 0 {
291+
return f[i]
292+
}
293+
node := trie
294+
f[i] = inf
295+
for j := i; j < n; j++ {
296+
k := int(target[j] - 'a')
297+
if node.children[k] == nil {
298+
break
299+
}
300+
f[i] = min(f[i], 1+dfs(j+1))
301+
node = node.children[k]
302+
}
303+
return f[i]
304+
}
305+
if ans := dfs(0); ans < inf {
306+
return ans
307+
}
308+
return -1
309+
}
310+
```
112311

312+
#### TypeScript
313+
314+
```ts
315+
class Trie {
316+
children: (Trie | null)[] = Array(26).fill(null);
317+
318+
insert(word: string): void {
319+
let node: Trie = this;
320+
for (const c of word) {
321+
const i = c.charCodeAt(0) - 'a'.charCodeAt(0);
322+
if (!node.children[i]) {
323+
node.children[i] = new Trie();
324+
}
325+
node = node.children[i];
326+
}
327+
}
328+
}
329+
330+
function minValidStrings(words: string[], target: string): number {
331+
const n = target.length;
332+
const trie = new Trie();
333+
for (const w of words) {
334+
trie.insert(w);
335+
}
336+
const inf = 1 << 30;
337+
const f = Array(n).fill(0);
338+
339+
const dfs = (i: number): number => {
340+
if (i >= n) {
341+
return 0;
342+
}
343+
if (f[i]) {
344+
return f[i];
345+
}
346+
f[i] = inf;
347+
let node: Trie | null = trie;
348+
for (let j = i; j < n; ++j) {
349+
const k = target[j].charCodeAt(0) - 'a'.charCodeAt(0);
350+
if (!node?.children[k]) {
351+
break;
352+
}
353+
node = node.children[k];
354+
f[i] = Math.min(f[i], 1 + dfs(j + 1));
355+
}
356+
return f[i];
357+
};
358+
359+
const ans = dfs(0);
360+
return ans < inf ? ans : -1;
361+
}
113362
```
114363

115364
<!-- tabs:end -->

0 commit comments

Comments
 (0)