Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 36e6eb2

Browse files
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)

AltStyle によって変換されたページ (->オリジナル) /