单词拆分问题
单词拆分1
问题描述:
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
思路:
使用动态规划求解
代码
bool wordBreak(string s, vector<string>& wordDict) {
int len = s.size();
if(!len) return true;
bool dp[len+1] = {0};
dp[len] = true;
string word;
for(int i = len-1; i >= 0; i--){
word = "";
for(int j = i; j < len; j++){
word += s[j];
if(dp[j+1] && count(wordDict.begin(),wordDict.end(),word)){
dp[i] = true;
break;
}
}
}
return dp[0];
}
单词拆分2
问题描述:
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
说明:
分隔时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:
输入:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
输出:
[
"cats and dog",
"cat sand dog"
]
思路
首先会想到用深搜方法遍历所有可能的拆分状态,这是可行的,但要注意的是会出现这种情况:s = "aaaaaaaaaaaaaaaaaaaaaaab", wordDict = ["a","aa","aaa"],此时若依然无脑递归深搜,会出现大量的重复搜索最终却发现无法拆分,因此,需要记录s的某个后缀是否被递归过,避免重复性搜索后缀。
代码
vector<string> wordBreak(string s, vector<string>& wordDict) {
return dfs(s, wordDict, 0);
}
map<int, vector<string>> list;
vector<string> dfs(string& s, vector<string>& wordDict, int k){
if(list.count(k)) return list[k];
vector<string> res;
if(k == s.size()){
list[k] = res;
return list[k];
}
string word = "";
for(int i = k; i < s.size(); i++){
word += s[i];
if(count(wordDict.begin(),wordDict.end(),word)) {
if(i == s.size()-1) res.push_back(word);
else
for(string s : dfs(s, wordDict, i+1))
res.push_back(word + " " + s);
}
}
list[k] = res;
return res;
}