Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
For example, given
s = "leetcode"
,
dict = ["leet", "code"]
.
Return true because "leetcode"
can be segmented as "leet code"
.
题目要判断一个字符串能够切分为字典里已有的单词。这道题可以用递归+搜索解决,刚开始没有用记忆化搜索,结果超时,使用了后就能通过。
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
set<string> unmatch; //记录不能划分单词的字符串集合
if (canWordBreak(s, 0, unmatch, dict))
return true;
return false;
}
bool canWordBreak(string &s, int k, set<string> &unmatch, unordered_set<string> &dict) {
if (k==s.size())
return true;
string ss = "";
bool flag = false;
// stringset::hasher fn = dict.hash_function();
for (int i=k; i<s.size(); ++i) {
ss += s[i];
//unordered_set<string>::const_iterator got = dict.find(ss);
if (dict.find(ss) != dict.end()) {
if (unmatch.find(s.substr(i+1)) != unmatch.end()) //在位置i切分后,后面的字符串不能分割为单词
continue;
else {
flag = canWordBreak(s, i+1, unmatch, dict);
if (flag)
return true;
else
unmatch.insert(s.substr(i+1));
}
}
}
return false;
}
};
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.
Return all such possible sentences.
For example, given
s = "catsanddog"
,
dict = ["cat", "cats", "and", "sand", "dog"]
.
A solution is ["cats and dog", "cat sand dog"]
.
这题是对上题的扩展,要找出能划分单词的所有集合(单词间用空格隔开)。
class Solution {
public:
vector<string> wordBreak(string s, unordered_set<string> &dict) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
pattern.clear();
unmatch.clear();
ret = findWordBreak(s, 0, dict); //从位置0开始找的单词划分情况
return ret;
}
vector<string> findWordBreak(string &s, int k, unordered_set<string>&dict) {
string temp = "", subs;
vector<string> ans, rest; //ans存储位置k开始的全部句子
for (int i=k; i<s.size(); ++i) {
temp += s[i];
if (dict.find(temp) != dict.end()) { //词库中存在
if ((i+1) == s.size()) { // 从位置k开始的全部字符串是一个单词
ans.push_back(temp); // 把这种情况加入ans集合
break;
}
subs = s.substr(i+1);
if (unmatch.find(subs) != unmatch.end()) { //后面的字符串不能成为一个句子
continue;
}
if (pattern.find(subs) == pattern.end()) { //未搜索过后面的字符串划分单词的情况
pattern[subs] = findWordBreak(s, i+1, dict);
}
for (int j=0; j<pattern[subs].size(); ++j) { // 组合单词为句子,pattern[subs]可能为空,此时不能组成句子
ans.push_back(temp + " " + pattern[subs][j]);
}
}
}
temp = s.substr(k);
pattern[temp] = ans;
if (ans.empty())
unmatch.insert(temp);
return ans;
}
private:
map<string, vector<string>> pattern; //键为字符串,值为对应的空格隔开的单词集合(句子)
set<string> unmatch; // 存储不能划分单词的字符串
vector<string> ret;
};
后来想了想,其实不用存储不能组成句子的字符串集合unmatch的,因为对于那些字符串S,pattern已经存储了句子集合,而且句子集合为空,当前的单词不能和S组成句子,所以只用pattern就可以解决。
class Solution {
public:
vector<string> wordBreak(string s, unordered_set<string> &dict) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
pattern.clear();
ret = findWordBreak(s, 0, dict); //从位置0开始找句子
return ret;
}
vector<string> findWordBreak(string &s, int k, unordered_set<string>&dict) {
string temp = "", subs;
vector<string> ans, rest; //ans存储位置k开始的全部句子
for (int i=k; i<s.size(); ++i) {
temp += s[i];
if (dict.find(temp) != dict.end()) { //词库中存在
if ((i+1) == s.size()) { // 从位置k开始的全部字符串是一个单词
ans.push_back(temp); // 把这种情况加入ans集合
break;
}
subs = s.substr(i+1);
if (pattern.find(subs) == pattern.end()) { //未搜索过后面的字符串划分单词的情况
pattern[subs] = findWordBreak(s, i+1, dict);
}
for (int j=0; j<pattern[subs].size(); ++j) { // 组合单词为句子,pattern[subs]可能为空,此时不能组成句子
ans.push_back(temp + " " + pattern[subs][j]);
}
}
}
temp = s.substr(k);
pattern[temp] = ans;
return ans;
}
private:
map<string, vector<string>> pattern; //键为字符串,值为对应的空格隔开的单词集合(句子)
vector<string> ret;
};