題目:
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+DFS解決
這裡採用DP中的自底向上實現,dp[i]表示前i個字元能否進行Wordbreak。當求解dp[i]時,可利用已經求解的dp[i-1],
dp[i-2]…dp[1],dp[0]進行求解。
對於dp[n]的求解,我們可以將n個字元進行切分求解,分為前i個字元和後n-i個字元,i可以為(0,1,2,3,4…n-1)
假設i為1時,可根據dp[i]和後面的n-1個字元組成的單詞是否在dict中來判斷dp[n],只要i(0,1,2,3,4…n-1)其中一種
情況為真,則dp[n]為true,表示可以進行workbreak。
因為本題需要重構結果,所以必須要有一個資料結構來儲存每段長度的切割方案,這裡我用unordered_map<int, vector<int> >進行儲存,key為字元長度,vector儲存該key對應的切割方案。
如何求得unordered_map<int, vector<int> >中的值呢?那就應該利用求解dp[i]時,每當有一種切割方案使得dp[i]為true時,將其對應的切割位置存放到i對應的vector中,待之後用於結果重構。
unordered_map<int, vector<int> >求得後,接下來是採用DFS演算法進行結果重構,如程式碼執行結果圖,當長度為10時,有一種切割方案,即在長度為7的位置進行切割,然後長度為7的切割方案又有兩種3和4,長度為3和4時,切割方案都為0,所以採用DFS時,遍歷順序為7,3,0然後獲得一種結果,之後回溯到7,4,因為4的切割方案為0,所以為7,4,0,又是一種結果。
實現程式碼:
#include <iostream> #include <string> #include <vector> #include <unordered_set> #include <unordered_map> using namespace std; /* 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"]. */ class Solution { public: vector<string> wordBreak(string s, unordered_set<string> &dict) { vector<string> retvec; if(s.size() == 0 || dict.size() == 0) return retvec; int len = s.size(); vector<bool> dp(len+1, false);//儲存狀態,dp[i]表示前i個字元是否可以進行wordBread unordered_map<int, vector<int> > hash_map;// 存放使得dp[i]為true的切割方案 dp[0] = true; for(int i = 1; i <= len; i++) { vector<int> vec; for(int j = 0; j < i; j++) { if(dp[j] && dict.count(s.substr(j, i-j)) == 1)//對前i個字元進行切分時,只要有一種情況為true,則dp[i]=true { dp[i] = true; vec.push_back(j);//放使得dp[i]為true的切割方案 } } hash_map[i] = vec; } for(int k = 1; k <= len; k++) { vector<int> tvec = hash_map[k]; cout<<k<<":"; vector<int>::iterator iter; for(iter = tvec.begin(); iter != tvec.end(); ++iter) { cout<<*iter<<" "; } cout<<endl; } vector<int> curVec; getResult(hash_map, s, len, retvec, curVec); return retvec; } //採用DFS解決 void getResult(unordered_map<int, vector<int> > &hash_map,string s, int len, vector<string> &retvec, vector<int> &curVec) { if(len == 0) { string t; int start = 0; for(int i = curVec.size()-2; i >= 0; i--) { int c = curVec[i]; t += s.substr(start, c-start); t += " "; start = c; } t += s.substr(curVec[0]); retvec.push_back(t); return ; } vector<int> tvec = hash_map[len]; vector<int>::iterator iter; for(iter = tvec.begin(); iter != tvec.end(); ++iter) { curVec.push_back(*iter); getResult(hash_map, s, *iter, retvec, curVec); curVec.pop_back(); } } }; int main(void) { string s("catsanddog"); unordered_set<string> dict; dict.insert("cat"); dict.insert("cats"); dict.insert("and"); dict.insert("sand"); dict.insert("dog"); Solution solution; vector<string> retvec = solution.wordBreak(s, dict); vector<string>::iterator iter; for(iter = retvec.begin(); iter != retvec.end(); ++iter) cout<<*iter<<endl; return 0; }
執行結果: