Word Break II (LeetCode)
Question:
https://oj.leetcode.com/problems/word-break-ii/
解答:
跟Word Break类似,只不过把bool变量变成vector<int>,保存所有能够跟当前点形成一个有效word的点,并且那个点本身的vector<int>不为空(等同于bool flag = true)。所以我们从点(n-1)开始回溯,就能遍历所有点。
比如:
For example, given
s = "catsanddog"
,
dict = ["cat", "cats", "and", "sand", "dog"]
.
我们就能得到如下的vector<int>:
index vector<int>
0('c') {}
1('a') {}
2('t') {-1}
3('s') {-1}
4('a') {}
5('n') {}
6('d') {2, 3}
7('d') {}
8('o') {}
9('g') {6}
从9开始回溯,形成的组合就有:{6, 3, -1}, {6, 2, -1},这些值其实也就是相当于在原字符串往后插入空格的位置(省略-1).
遍历能用DFS, BFS,其中递归的BFS最容易写。
class Solution { public: vector<string> wordBreak(string s, unordered_set<string> &dict) { vector<string> ret; int n = s.size(); if (n==0) return ret; vector<vector<int>> prevWordEndsArray (n); for (int i = 0; i < n; i++) { for (int j = 0; j <= i; j++) { if ((j == 0 || prevWordEndsArray[j-1].size() > 0) && dict.find(s.substr(j, i-j+1)) != dict.end()) prevWordEndsArray[i].push_back(j-1); } } vector<int> vempty; BackTrace(prevWordEndsArray, n-1, s, ret, vempty); return ret; } void BackTrace(vector<vector<int>>& prevWordEndsArray, int arrayIndex, string& s, vector<string>& ret, vector<int>& breaks) { for (int i = 0; i < prevWordEndsArray[arrayIndex].size(); i++) { if (prevWordEndsArray[arrayIndex][i] == -1) { // found one AddBreaksToString(ret, s, breaks); } else { vector<int> newBreaks = breaks; newBreaks.push_back(prevWordEndsArray[arrayIndex][i]); BackTrace(prevWordEndsArray, prevWordEndsArray[arrayIndex][i], s, ret, newBreaks); } } } void AddBreaksToString(vector<string>& ret, string& s, vector<int>& breaks) { string wd = s; for (int i = 0; i < breaks.size(); i++) { // The value in breaks is from right to left wd.insert(breaks[i]+1, " "); } ret.push_back(wd); } };