zoukankan      html  css  js  c++  java
  • 140. Word Break II

    Problem statement:

    Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. You may assume the dictionary does not contain duplicate words.

    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"].

    Solution one: Dynamic programming

    We can use dynamic programming to solve this problem. But, it cause TLE since we did not record all possible solutions. 

    keep two arrays, one is for dynamic programming,

    vector<bool> dp(size + 1, false); 
    • It records if s.substr(0, size) is breakable or not. 
    • dp[0] is true, "" is a solution.

    Another array keep the all possible solutions for current position

    vector<vector<string>> components(size + 1);

    The code is as following:

    class Solution {
    public:
        vector<string> wordBreak(string s, vector<string>& wordDict) {
            vector<string> sentences;
            int size = s.size(); 
            vector<vector<string>> components(size + 1);
            components[0].push_back("");
    
            // initialize the dp array
            // dp[0] is true for following iteration
            vector<bool> dp(size + 1, false);
            dp[0] = true;
            for(int i = 1; i <= size; i++){
                for(int j = 0; j < i; j++){
                    if(dp[j] && find(wordDict.begin(), wordDict.end(), s.substr(j, i - j)) != wordDict.end()){
                        dp[i] = true;
                        // update sentence components array
                        for(vector<string>::size_type ix = 0; ix < components[j].size(); ix++){
                            // get to the end of s and it is also a sentence
                            // add it to the sentences
                            if(i == size){
                                if(j == 0){
                                    sentences.push_back(s.substr(j, i - j));
                                } else {
                                    sentences.push_back(components[j][ix] + " " + s.substr(j, i - j));
                                }
                            } else {
                                if(j == 0){
                                    // the first word in the sentence
                                    components[i].push_back(s.substr(j, i - j));
                                } else {
                                    // not the first word in the sentence
                                    components[i].push_back(components[j][ix] + " " + s.substr(j, i - j));
                                } 
                            }
                        }
                    }
                }
            }
            return sentences;
        }
    };

    solution two: DFS without return value(AC)

    This problem need to return all possible sentences. It is DFS. But, it is not simply do DFS, we need pruning while searching, to reduce the workload, otherwise, it will cause TLE. 
    Keep an array(s.size() + 1), it records whether the string is breakable from current position to the end.

    class Solution {
    public:
        vector<string> wordBreak(string s, vector<string>& wordDict) {
            vector<string> sentence_set;
            vector<int> isbreak(s.size() + 1, true);
            string sentence;
            word_break_dfs(wordDict, sentence_set, isbreak, s, sentence, 0);
            return sentence_set;
        }
    private:
        void word_break_dfs(vector<string>& wordDict, 
                            vector<string>& sentence_set, 
                            vector<int>& isbreak,
                            string& s, 
                            string& sentence, 
                            int start){
            if(start == s.size()){
                // reach to the end, find one solution
                // -1 is for " "
                sentence_set.push_back(sentence.substr(0, sentence.size() - 1));
                return;
            }
            for(int i = start + 1; i <= s.size(); i++){
                string word = s.substr(start, i - start);
                // find a new word in dictionary
                // the word is brakable from i to the end of the sentence.
                if(find(wordDict.begin(), wordDict.end(), word) != wordDict.end() && isbreak[i]){
                    // update the sentence
                    sentence += word + " ";
                    // keep a size to update isbreak array
                    int size = sentence_set.size();
                    word_break_dfs(wordDict, sentence_set, isbreak, s, sentence, i);
                    if(sentence_set.size() == size){
                        isbreak[i] = false;
                    }
                    // resize the sentence
                    sentence.resize(sentence.size() - word.size() - 1);
                }
            }
            return;
        }
    };

    Solution three: DFS with return value(AC)

    In this solution, the return value of DFS function is vector<string>, it stores all possible sentences when we pass a string to it. Thhere is a hash table to store all the values we already got, to prune the DFS search.

    class Solution {
    public:
        vector<string> wordBreak(string s, vector<string>& wordDict) {
            unordered_map<string, vector<string>> str_table;
            return word_break_dfs(s, wordDict, str_table);
        }
    private:
        vector<string> word_break_dfs(  string str, 
                                        vector<string>& wordDict, 
                                        unordered_map<string, vector<string>>& str_table){
            // already get the value of current string
            if(str_table.find(str) != str_table.end()){
                return str_table[str];
            }
            if(str.empty()){
                // DFS stop condition
                return {""};
            }
            vector<string> sentences_set;
            for(int i = 1; i <= str.size(); i++){
                string word = str.substr(0, i);
                if(find(wordDict.begin(), wordDict.end(), word) != wordDict.end()){
                    // current word in dictionary, do DFS search
                    vector<string> word_set = word_break_dfs(str.substr(i, str.size() - 1), wordDict, str_table);
                    for(auto component : word_set){
                        // add the value to return set
                        sentences_set.push_back(word + (component.empty()? "" : " ") + component);
                    }
                }
            }
            // store current value to hash table for future prune
            str_table[str] = sentences_set;
            return sentences_set;
        }
    };
  • 相关阅读:
    android 进程/线程管理(一)----消息机制的框架
    android的屏幕保持常亮
    android network develop(3)----Xml Parser
    android network develop(2)----network status check
    android network develop(1)----doing network background
    android 开发小记
    转 Android中shape中的属性大全
    转 Android学习 之 ColorStateList按钮文字变色
    《大话设计模式》c++实现 建造者模式
    《大话设计模式》c++实现 外观模式
  • 原文地址:https://www.cnblogs.com/wdw828/p/6839048.html
Copyright © 2011-2022 走看看