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"]
.
写了整整2天!
一直没有碰上过5星的题,碰上了才知道厉害T。T。
dp直接记录下i能够到达的j,且要求J能够到达字符串末端,否则不记录j。虽然它依旧是淳朴的dp+dfs,可是上面那个记录,让它的复杂度噌噌噌降到了O(N^2)* O (dp)!人生如此美好
预处理:tbl[i]事先记录能够到达的位置j。深搜中会多次比较(i, j) 字符串是否属于字典,所以预先处理、记录可以节省很多时间。
class Solution {
public:
vector<string> wordBreak(string s, unordered_set<string> &dict) {
vector<string> ans;
vector<vector<int> > tbl = dp(s, dict);
dfs(0, s.length(), "", ans, s, dict, tbl);
return ans;
}
vector<vector<int> > dp(string s, unordered_set<string> dict) {
int len = s.length();
vector<vector<int> > tbl(len);
//both i and j infer index
//from i to len - 1, is it a word?
for (int i = 0; i < len; i++) {
if (dict.find(s.substr(i)) != dict.end()) {
tbl[i].push_back(len - 1);
}
}
//from j to i, is it a word? can it extends to len - 1?
for (int i = len - 2; i >= 0; i--) {
if (tbl[i + 1].empty())
continue;
for (int j = i; j >= 0; j--) {
if (dict.find(s.substr(j, i - j + 1)) != dict.end()) {
tbl[j].push_back(i);
}
}
}
return tbl;
}
void dfs(int st, int len, string cur, vector<string> &ans, string s, unordered_set<string> &dict, vector<vector<int> > &tbl) {
if (st == len) {
ans.push_back(cur);
return;
}
//candidate
vector<int> can = tbl[st];
int size = can.size();
for (int i = 0; i < size; i++) {
string tmp = cur;
if (tmp != "")
tmp += " ";
tmp += s.substr(st, can[i] - st + 1);
dfs(can[i] + 1, len, tmp, ans, s, dict, tbl);
}
}
};