Code:
class Solution {
public:
vector<string> wordBreak(string s, unordered_set<string>& wordDict) {
vector<string> res;
if(s.empty()) return res;
int n = s.length();
vector<vector<int>> prev(n,vector<int>());
if(!dp(s, wordDict, prev)) return res;
dfs(n-1, "", s, prev,res);
return res;
}
void dfs(int cur, string member, string &s, vector<vector<int>> &prev, vector<string> &res ){
if(cur<0){
res.push_back(member);
return;
}
for(int i = 0; i < prev[cur].size(); i++){
string temp;
if(cur == s.length() - 1){
temp = s.substr(prev[cur][i], cur - prev[cur][i] + 1) + member;
}else{
temp = s.substr(prev[cur][i], cur - prev[cur][i] + 1) + " " + member;
}
dfs(prev[cur][i]-1, temp, s, prev, res );
}
}
bool dp(string &s, unordered_set<string>& wordDict, vector<vector<int>> &prev){
//prev[i] = j means s[j...i] is a word in dict
int n = s.length();
vector<bool> dp(n,false); //dp[i] means s[0....i] can formed by the dict
for(int i = 0 ; i < n; i ++){
if(wordDict.find(s.substr(0,i+1))!=wordDict.end()) {
dp[i] = true;
prev[i].push_back(0);
}
for(int j = 0; j < i; j ++){
if(dp[j] && wordDict.find(s.substr(j+1,i-j))!=wordDict.end()){
dp[i] = true;
prev[i].push_back(j+1); //since s[0...j] and s[j+1...i] are in dict, so we remember s[j+1...i] could be a part of valid combination.
}
}
}
return dp[n-1];
}
};