@@ -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