- Word Break
Given a string s and a dictionary of words dict, determine if s can be break into a space-separated sequence of one or more dictionary words.
Example
Given s = “lintcode”, dict = [“lint”, “code”].
Return true because “lintcode” can be break as “lint code”.
解法1:DFS。超時 (95%的時候)
class Solution {
public:
/*
* @param s: A string
* @param dict: A dictionary of words dict
* @return: A boolean
*/
bool wordBreak(string &s, unordered_set<string> &dict) {
int lenS = s.size();
int lenD = dict.size();
maxWordLen = 0;
minWordLen = lenS;
for (auto w : dict) {
maxWordLen = max(maxWordLen, (int)w.size());
minWordLen = min(minWordLen, (int)w.size());
}
vector<string> sol;
vector<vector<string>> result;
helper(s, dict, sol, result);
if (result.size() > 0) return true;
return false;
}
private:
void helper(string &s, unordered_set<string> &dict, vector<string> &sol, vector<vector<string>> &result) {
int len = s.size();
if (len == 0) {
result.push_back(sol);
return;
}
if (len < minWordLen)
return;
for (int i = minWordLen; i <= maxWordLen; ++i) {
string w = s.substr(0, i);
if (dict.find(w) == dict.end()) continue;
sol.push_back(w);
string newStr = s.substr(i, len - i);
helper(newStr, dict, sol, result);
sol.pop_back();
}
}
int minWordLen;
int maxWordLen;
};
解法2:還是DFS,s不動index動。Pass。
class Solution {
public:
/*
* @param s: A string
* @param dict: A dictionary of words dict
* @return: A boolean
*/
bool wordBreak(string &s, unordered_set<string> &dict) {
int lenS = s.size();
int lenD = dict.size();
maxWordLen = 0;
minWordLen = lenS;
for (auto w : dict) {
maxWordLen = max(maxWordLen, (int)w.size());
minWordLen = min(minWordLen, (int)w.size());
}
vector<string> sol;
vector<vector<string>> result;
helper(s, 0, dict, sol, result);
if (result.size() > 0) return true;
return false;
}
private:
void helper(string &s, int index, unordered_set<string> &dict, vector<string> &sol, vector<vector<string>> &result) {
int len = s.size();
if (index == len) {
result.push_back(sol);
return;
}
if (index + minWordLen > len) //剪枝
return;
for (int i = minWordLen; i <= maxWordLen; ++i) {
string w = s.substr(index, i);
if (dict.find(w) == dict.end()) continue;
sol.push_back(w);
helper(s, index + i, dict, sol, result);
sol.pop_back();
}
}
int minWordLen;
int maxWordLen;
};
解法3:DFS+Memorization
即把s分成str1和str2,如果str1在dict中則可調用子問題,輸入爲str2。
Memozation可以減枝。
代碼如下:
class Solution {
public:
/*
* @param s: A string
* @param dict: A dictionary of words dict
* @return: A boolean
*/
bool wordBreak(string &s, unordered_set<string> &dict) {
if (s.size() == 0 && dict.size() == 0) return true;
unordered_map<string, bool> memo;
return helper(s, dict, memo);
}
private:
bool helper(string &s, unordered_set<string> &dict, unordered_map<string, bool> & memo) {
if (s.size() == 0) return false;
if (memo.find(s) != memo.end()) return memo[s];
int len = s.size();
for (int i = 1; i <= len; ++i) {
string subStr1 = s.substr(0, i);
if (dict.find(subStr1) != dict.end()) {
if (subStr1 == s) {
memo[s] = true;
return true;
}
string subStr2 = s.substr(i);
bool result = helper(subStr2, dict, memo);
if (result) {
memo[s] = true;
return true;
}
}
}
memo[s] = false;
return false;
}
};