题目描述
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
说明:
- 分隔时可以重复使用字典中的单词。
- 你可以假设字典中没有重复的单词。
示例 1:
输入:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
输出:
[
"cats and dog",
"cat sand dog"
]
示例 2:
输入: s = "pineapplepenapple" wordDict = ["apple", "pen", "applepen", "pine", "pineapple"] 输出: [ "pine apple pen apple", "pineapple pen apple", "pine applepen apple" ] 解释: 注意你可以重复使用字典中的单词。
示例 3:
输入: s = "catsandog" wordDict = ["cats", "dog", "sand", "and", "cat"] 输出: []
问题分析
此题和上一道类似,还是用DFS来做。同样的,我们需要一个哈希表<string, vector<string>> memo来记录字符串s被拆分的结果。这样如果后面在递归求解某子串s被拆分的结果时,如果这个子串s在之前求出并存入了哈希表memo,就可以直接取出结果并返回。将字符串s传入DFS函数开始递归,先在哈希表memo中找,如果找到了直接返回已有结果。如果字符串为空,那么返回{""},然后定义一个vector<string>数组out。接下来开始for循环,在数组wordDict中遍历字符串,当遇到某一个字符串与s中开头部分匹配的话,把字符串s中除了开头剩下的部分传入DFS函数中进行计算,然后把返回的结果赋值给临时数组vector<string> temp,然后我们取数组temp中的每一个字符串记为ss。然后我们把刚才s开头匹配的str加上空格" "再加上一个ss组成一个新的字符串,这个新的字符串为拆分结果之一,把它push_back进out里面。当然如果ss是空的话,我们就不要空格了,那么将要加入out的新字符串其实就是字符串s的末尾那个单词,只有到末尾时才有这种情况。在for循环结束后,数组out中保存的就是字符串s的所有可能拆分的结果。所以我们将字符串s与对应的结果组合out记录在哈希表memo中,并返回。
代码实现
class Solution {
public:
vector<string> wordBreak(string s, vector<string>& wordDict) {
unordered_map<string, vector<string>> memo;
return DFS(s, wordDict, memo);
}
vector<string> DFS(string s, vector<string>& wordDict, unordered_map<string, vector<string>>& memo){
if(memo.count(s))
return memo[s];
if(s.empty())
return {""};
vector<string> out;
for(string str : wordDict){
if(s.substr(0, str.size()) == str){
vector<string> temp = DFS(s.substr(str.size()), wordDict, memo);
for(string ss : temp)
out.push_back(str + (ss.empty()? "" : " ") + ss);
}
}
memo[s] = out;
return memo[s];
}
};