Topic:
Given A string s and a Dictionary of words dict, add spaces in s to construct a sentence where Each of the word is a valid dictionary word.
Return all such possible sentences.
for example, given
s = " Catsanddog "
,
dict = < Code style= "Font-family:menlo,monaco,consolas, ' Courier New ', monospace; font-size:13px; PADDING:2PX 4px; Color:rgb (199,37,78); Background-color:rgb (249,242,244) ">[" Cat "," Cats "," and "," sand "," dog "] .
A solution is ["cats and dog", "cat sand dog"]
.
Answer 1:BF Recursive Solution TLE
idea: each time you maintain a current result set, and then iterate through all the remaining substrings, if the substring appears in the dictionary, save the result. And put all the remaining characters in the next layer recursively.
However, this practice will time out in Leetcode.
Error Code:
Class Solution {public: vector<string> wordbreak (string s, unordered_set<string> &dict) { vector<string> ret; if (s.size () = = 0) return ret; Wordbreak_helper (S, dict, 0, "", ret); return ret; } Private: void Wordbreak_helper (string s, unordered_set<string>& dict, int pos, string tmp, vector< string>& ret) { if (pos = = S.size ()) { ret.push_back (tmp.substr (0, Tmp.size ()-1)); Remove space return; } for (int i = pos; i < S.size (), i++) {for (int j = 1; J < S.size ()-I; + j) { string substr = s.su BSTR (POS, j); if (Dict.find (substr)! = Dict.end ()) { Wordbreak_helper (S, Dict, i+1, tmp + "" + substr, ret); } } } }};
Answer 2: Join DP
idea: This problem, we learn from word break in the dynamic planning ideas. But this time we need to record each split result, so we use a two-dimensional array to save dynamic programming results, two-dimensional array form vector<list<int>> DP, Dp[i] to represent the string from the coordinate i The list of terminating positions for all legal words that begin. We start from the end of the string, from the bottom up to solve the dynamic layout of the array, we take the current stop as the terminating position, loop all the legal start position, if the substring in the dictionary, the corresponding in the DP array to add elements. It is important to note that if there are no matching dictionary words from the current stop (the description is not broken here), you can skip this stop as a cutoff position.
After solving all possible combinations, we use backtracking to solve all possible segmentation situations. This time from top to bottom, start with the string header and iterate through all the results until the end of the string is reached.
Attention:
1. Stop means the last bit of the end of the word, that is, the first or string length of the next word. So stop starts with s.size ().
for (int stop = S.size (); stop >= 0; stop--)
2. If there are no dictionary words starting from the current stop, you can skip this breakpoint.
If there are no matching words starting from stop, you can skip the stop word that examines this stops coordinate (stop indicates the last digit of the word) if (Stop < S.size () && Mark[stop].empty ( )) continue;
3. Starting from the current stop, loop through all legitimate start positions and update the dynamic Plan array.
/check all words in the dictionary before the current stop cutoff, and add them into mark. For (int start = stop-1; start >= 0; start--) { String substr = S.substr (start, stop-start); if (Dict.find (substr)! = Dict.end ()) { mark[start].push_back (stop);} }
4. New usage of c++11 for.
The For statement will allow a simple range iteration:
intMy_array[5] = {1,2,3,4,5}; for (int &X:My_array){X*= 2;}
for The first part of the definition of the sentence is used to make the parameters of the range iteration, just like the parameters declared in the general for loop, whose scope is only the scope of the loop. The second block after the ":" represents the range that will be iterated. Also, a loop variable is a reference that can change its value in a loop.
For (int& Stop:mark[index])
In the program, this sentence represents the stop position of all the words starting with index.
5. When backtracking, we note that to maintain the current path, you cannot replace the path with a new string that adds a substring, because this is a looping statement, and we will still use the original path for the next stop (no substring added).
For (int& Stop:mark[index]) { string substr = S.substr (index, stop-index); String NewPath = Path + (index = = 0? substr: "" + substr);
AC Code:
Class Solution {public:vector<string> Wordbreak (string s, unordered_set<string> &dict) {//mark [I] stores all the cutoff coordinates of a word in the dictionary, starting with the I coordinate. Vector<list<int>> Mark (S.size (), list<int> ()); From the end of the string to the head for (int stop = S.size (); stop >= 0; stop--) {//If there are no matching words starting from stop, you can skip the closing order to review this stop coordinate The word (stop indicates the last digit of the word) if (Stop < S.size () && mark[stop].empty ()) continue; Check all the words in the dictionary before the current stop cutoff, and add them into mark. for (int start = stop-1; start >= 0; start--) {String substr = S.substr (Start, Stop-start ); if (Dict.find (substr)! = Dict.end ()) {mark[start].push_back (stop); }}} vector<string> ret; Generate (Mark, 0, S, "", ret); return ret; }private:void Generate (vector<list<int>> mark, int index, const string& s, stringPath, vector<string>& ret) {for (int& Stop:mark[index]) {string substr = s.su BSTR (Index, STOP-INDEX); String NewPath = Path + (index = = 0? substr: "" + substr); if (stop = = S.size ()) Ret.push_back (NewPath); else generate (Mark, stop, S, NewPath, ret); } }};
This problem is very comprehensive, it is difficult to combine DP and backtracking, especially the method of setting up DP array can be used for reference.
[C + +] leetcode:113 Word break II (DP && backtacking) solution split combination