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"]
.
这道题是 Word Break 的一个拓展
问题:根据给的单词字典,求一个字符串所有可能的有效分割。
有了 Word Break 的经验,这道题做起来也顺畅了许多。
假设将字符串 s 分割为两段,[0,i-1], [i, n-1],如果[0, i-1] 为有效单词,[i, n-1]为有效单词集合,那么 s 就是一个有效字符串。将 [0, i-1] 依次和 [i, n-1] 所有可能分别匹配,则得到 s 以 i 为分割点得全部有效分割。
将 i 从 1 到 n-1 遍历一次,则求得 s 的全部分割的可能。
和 Word Break 一样,需要记录已计算的结果,提高效率。利用 map<int, vector<string>> idx_words[k] 来记录 [k, n-1] 子串的全部有效分割。
map<int, vector<string>> idx_words; vector<string> match(string s, unordered_set<string>& wordDict, int startIdx){ vector<string> res; for (int i = 1 ; i < s.size(); i++) { string leftS = s.substr(0, i); unordered_set<string>::iterator us_iter = wordDict.find(leftS); if (us_iter != wordDict.end()) { int rightRLIdx = i + startIdx; vector<string> rightV; if (idx_words.find(rightRLIdx) != idx_words.end()){ rightV = idx_words[rightRLIdx]; }else{ string rightS = s.substr(i, s.size() - i); rightV = match(rightS, wordDict, rightRLIdx); idx_words[rightRLIdx] = rightV; } for (int ii = 0; ii < rightV.size(); ii++) { string tmpS = leftS + " " + rightV[ii]; res.push_back(tmpS); } } } if (wordDict.find(s) != wordDict.end()) { res.push_back(s); } return res; } vector<string> wordBreak(string s, unordered_set<string>& wordDict) { vector<string> res; res = match(s, wordDict, 0); return res; }