LeetCode 题解工作台
形成目标字符串需要的最少字符串数 I
给你一个字符串数组 words 和一个字符串 target 。 如果字符串 x 是 words 中 任意 字符串的 前缀 ,则认为 x 是一个 有效 字符串。 现计划通过 连接 有效字符串形成 target ,请你计算并返回需要连接的 最少 字符串数量。如果无法通过这种方式形成 target ,则返…
9
题型
5
代码语言
3
相关题
当前训练重点
中等 · 状态·转移·动态规划
答案摘要
我们可以使用字典树存储所有有效字符串,然后使用记忆化搜索计算答案。 我们设计一个函数 ,表示从字符串 的第 个字符开始,需要连接的最少字符串数量。那么答案就是 。
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路
题目描述
给你一个字符串数组 words 和一个字符串 target。
如果字符串 x 是 words 中 任意 字符串的 前缀,则认为 x 是一个 有效 字符串。
现计划通过 连接 有效字符串形成 target ,请你计算并返回需要连接的 最少 字符串数量。如果无法通过这种方式形成 target,则返回 -1。
示例 1:
输入: words = ["abc","aaaaa","bcdef"], target = "aabcdabc"
输出: 3
解释:
target 字符串可以通过连接以下有效字符串形成:
words[1]的长度为 2 的前缀,即"aa"。words[2]的长度为 3 的前缀,即"bcd"。words[0]的长度为 3 的前缀,即"abc"。
示例 2:
输入: words = ["abababab","ab"], target = "ababaababa"
输出: 2
解释:
target 字符串可以通过连接以下有效字符串形成:
words[0]的长度为 5 的前缀,即"ababa"。words[0]的长度为 5 的前缀,即"ababa"。
示例 3:
输入: words = ["abcdef"], target = "xyz"
输出: -1
提示:
1 <= words.length <= 1001 <= words[i].length <= 5 * 103- 输入确保
sum(words[i].length) <= 105。 words[i]只包含小写英文字母。1 <= target.length <= 5 * 103target只包含小写英文字母。
解题思路
方法一:字典树 + 记忆化搜索
我们可以使用字典树存储所有有效字符串,然后使用记忆化搜索计算答案。
我们设计一个函数 ,表示从字符串 的第 个字符开始,需要连接的最少字符串数量。那么答案就是 。
函数 的计算方式如下:
- 如果 ,表示字符串 已经遍历完了,返回 ;
- 否则,我们可以从字典树中找到以 开头的有效字符串,然后递归计算 ,其中 是找到的有效字符串。我们取这些值中的最小值加 作为 的返回值。
为了避免重复计算,我们使用记忆化搜索。
时间复杂度 ,空间复杂度 。其中 是字符串 的长度,而 是所有有效字符串的总长度。
def min(a: int, b: int) -> int:
return a if a < b else b
class Trie:
def __init__(self):
self.children: List[Optional[Trie]] = [None] * 26
def insert(self, w: str):
node = self
for i in map(lambda c: ord(c) - 97, w):
if node.children[i] is None:
node.children[i] = Trie()
node = node.children[i]
class Solution:
def minValidStrings(self, words: List[str], target: str) -> int:
@cache
def dfs(i: int) -> int:
if i >= n:
return 0
node = trie
ans = inf
for j in range(i, n):
k = ord(target[j]) - 97
if node.children[k] is None:
break
node = node.children[k]
ans = min(ans, 1 + dfs(j + 1))
return ans
trie = Trie()
for w in words:
trie.insert(w)
n = len(target)
ans = dfs(0)
return ans if ans < inf else -1
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | Depends on the final approach |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
They hint with dp[i] as the minimum cost for the first i target characters, which points directly to prefix DP transitions.
- question_mark
They stress that a valid string is any prefix of a word, signaling that transitions are not limited to full dictionary words.
- question_mark
They include impossible cases like target starting with an unseen letter, testing whether you leave unreachable DP states untouched.
常见陷阱
外企场景- error
Treating only complete words as usable pieces, which misses valid shorter prefixes and returns counts that are too high or incorrectly -1.
- error
Using greedy longest-prefix choices, which can trap you in a bad suffix even when a shorter current split leads to the true minimum.
- error
Updating dp from every index without checking reachability first, causing meaningless work and hiding why some targets are impossible.
进阶变体
外企场景- arrow_right_alt
Build a trie over words so each target start index walks matching prefixes once instead of rescanning every word.
- arrow_right_alt
Precompute the longest valid extension from each target position, then run DP or greedy-style interval expansion on those ranges.
- arrow_right_alt
Change the objective from minimum number of pieces to number of ways, which keeps the same state graph but changes the DP aggregation.