標籤:leetcode
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那題的DP思路,首先,從尾部開始逆向看字串 s ,迴圈截取一個存在的詞(milestone 1),然後在截取的位置遞迴,繼續向前看,繼續截取。。。知道到達頭部,此時組合出一種答案;然後進入milestone 1 處的下一次迴圈,如的milestone 1
‘,截取另外一個詞,找另外一個答案。。。
代碼如下:
class Solution { vector<string> midres; vector<string> res; vector<bool> *dp;public: vector<string> wordBreak(string s, unordered_set<string> &dict) { int len = s.length(); dp = new vector<bool>[len]; for(int i=0; i<len; ++i){ for(int j=i; j<len; ++j){ if(dict.find(s.substr(i, j-i+1))!=dict.end()){ dp[i].push_back(true); //第二維的下標實際是:單詞長度-1 }else{ dp[i].push_back(false); //數組第二維用vector,size不一定是n,這樣比n*n節省空間的 } } } func(s, len-1); return res; } void func(const string &s, int i){ if(i>=0){ for(int j=0; j<=i; ++j){ if(dp[j][i-j]){ //注意此處的第二個下標是 i-j,不是i,因為數組的第二維長度是不固定的,第二維的下標實際是單詞長度-1 midres.push_back(s.substr(j, i-j+1)); func(s, j-1); midres.pop_back(); //繼續考慮for迴圈的下一個分段處 } } return; } else{ string str; for(int k=midres.size()-1; k>=0; --k){ //注意遍曆的順序是倒序的 str += midres[k]; //注意此處是k,不是i if(k>0) str += " "; } res.push_back(str); return; } }};
注意遞迴函式的技巧,用全域變數res來儲存答案,每次遞迴成功到達頭部時將此中間結果儲存到res。