页面加载中…
通过率 46% · 提交 72 · 通过 33
这道 OJ 的配套动画
单词拆分 · 对应本题的思路、过程和代码
给定字符串 s 和一个单词字典 wordDict,请判断 s 是否可以由字典中的一个或多个单词拼接而成。字典中的单词可以重复使用。
这题属于 Hot100 ACM 开放训练中的「字符串 DP」方向。建议先看动画确认核心思路,再回到右侧编辑器按标准输入输出写完整代码。
第一行输入字符串 s。第二行输入整数 m。接下来 m 行,每行一个单词。
如果可以拆分,输出 YES;否则输出 NO。
示例 1
输入示例
leetcode 2 leet code
输出示例
YES
leetcode = leet + code。
时间限制 2000 ms · 内存限制 256 MB
训练营动画视频讲解
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
设 dp[i] 表示 s 的前 i 个字符能否由词典中的单词拼成,空前缀可行,所以 dp[0]=true。计算 dp[i] 时枚举最后一个单词的起点 j;若 dp[j] 为真且 s[j:i] 在词典中,则这个前缀可以拆分。
该转移枚举了最后一个单词的全部可能起点,因此不会漏解;每个转移又只从已经可拆分的前缀扩展,所以不会产生错误方案。设最长单词长度为 L,每个位置最多检查 L 个起点,当前实现还要构造和哈希长度至多 L 的子串,最坏时间复杂度 O(nL²),空间复杂度 O(n+词典总字符数)。输入中的单词既可能逐行也可能空格分隔,按 token 读取可同时处理。
import sys
data = sys.stdin.buffer.read().split()
if not data:
raise SystemExit
text = data[0].decode()
word_count = int(data[1])
dictionary = {token.decode() for token in data[2 : 2 + word_count]}
max_word_length = max(map(len, dictionary), default=0)
possible = [False] * (len(text) + 1)
possible[0] = True # 空前缀不需要任何单词,可以被拆分。
for end in range(1, len(text) + 1):
first_start = max(0, end - max_word_length)
for start in range(first_start, end):
# 前缀可拆分,且最后一段是词典单词时,当前前缀可拆分。
if possible[start] and text[start:end] in dictionary:
possible[end] = True
break
print("YES" if possible[len(text)] else "NO")