1.普通版
题目:
给定一个非空字符串
s
和一个包含非空单词列表的字典
wordDict
,判定
s
是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
- 拆分时可以重复使用字典中的单词。
- 你可以假设字典中没有重复的单词。
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
示例 2:
输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。
注意你可以重复使用字典中的单词。
示例 3:
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false
解题思路:
题目的要求就是,一个字符串必须刚好被分为几个单词且这几个单词都在词典里,像实例3那样子交叉着是不行的,要独立分出来(一个单词一个单词的判断,截取需要的单词到最近的字符),其实这样就反而简单了呢。
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
n=len(s)
dp=[False]*(n+1)
dp[0]=True
for i in range(n):
for j in range(i+1,n+1):
if(dp[i] and (s[i:j]in wordDict)):
dp[j]=True
return dp[-1]
2.升级版
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
说明:
- 分隔时可以重复使用字典中的单词。
- 你可以假设字典中没有重复的单词。
示例 1:
输入:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
输出:
[
"cats and dog",
"cat sand dog"
]
解题思路:
不能像第一种那样从前往后推, 只能从后往前退,并且运用动态规划+回朔的方法。
from collections import deque
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
size = len(s)
assert size > 0
word_set = {word for word in wordDict}
dp = [0 for _ in range(size + 1)]#0~size
dp[0] = 1
for i in range(1, size + 1):#i: 1~size
for j in range(i):#j: 0~i-1
if dp[j] and s[j:i] in word_set:#0~j-1 true; j~i-1 in
dp[i] = 1
break
res = []
queue = deque()
self.__dfs(s, size, word_set, res, queue, dp)
return res
def __dfs(self, s, end, word_set, res, queue, dp):
if end == 0:
res.append(' '.join(queue))
return
for i in range(end): #0~end-1
if dp[i]: #0~i-1 true
suffix = s[i:end] #i~end-1
if suffix in word_set:
queue.appendleft(suffix)
self.__dfs(s, i, word_set, res, queue, dp) #0~i-1
queue.popleft()