140. Word Break II (Hard)

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

UPDATE (2017/1/4):
The wordDict parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.

Solution 1: DFS+DP 3ms

这道题是之前那道Word Break 拆分词句的拓展,那道题只让我们判断给定的字符串能否被拆分成字典中的词,而这道题加大了难度,让我们求出所有可以拆分成的情况,就像题目中给的例子所示。可以用DFS的套路来解题,但是不是一般的brute force,我们必须进行剪枝优化,因为按照惯例OJ的最后一个test case都是巨长无比的,很容易就Time Limit Exceeded。那么如何进行剪枝优化呢,可以参见网友水中的鱼的博客,定义一个一维数组possible,其中possible[i] = true表示在[i, n]区间上有解,n为s的长度,如果某个区间之前被判定了无解,下次循环时就会跳过这个区间,从而大大减少了运行时间,参见代码如下:

可以加上最大单词的长度来剪枝。

class Solution {
    void dfs(string& s, unordered_set<string>& m, vector<bool>& possible, 
            int maxlen, string out, int pos, vector<string>& res) {
        if (pos == s.size()) {
            out.pop_back();
            res.push_back(out);
            return;
        }
        for (int i = pos+1; i <= min(maxlen+pos,(int)s.size()); ++i) {
            string tmp = s.substr(pos, i-pos);
            if (possible[i] && m.count(tmp)) {
                int oldsize = res.size();
                dfs(s, m, possible, maxlen, out+tmp+' ', i, res);
                if (oldsize == res.size()) possible[i] = false;
            }
        }

    }
public:
    vector<string> wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> m;
        vector<bool> possible(s.size(), true);
        int maxlen = 0;
        for (string& word: wordDict) {
            m.insert(word);
            maxlen = max(maxlen, (int)word.size());
        }
        vector<string> res;
        dfs(s, m, possible, maxlen, "", 0, res);
        return res; 
    }
};

Solution 2: DFS+DP 13ms

class Solution {
    unordered_map<string, vector<string>> m;

    vector<string> combine(string word, vector<string> prev) {
        for (int i = 0; i < prev.size(); ++i) {
            prev[i] += " "+word;
        }
        return prev;
    }
public:
    vector<string> wordBreak(string s, unordered_set<string>& wordDict) {
        if (m.count(s)) return m[s]; // take from memory
        vector<string> res;
        if (wordDict.count(s)) {
            res.push_back(s); // a whole string is a word
        }
        for (int i = 1; i < s.size(); ++i) {
            string word = s.substr(i);
            if (wordDict.count(word)) {
                string rem = s.substr(0, i);
                vector<string> prev = combine(word, wordBreak(rem, wordDict));
                res.insert(res.end(), prev.begin(), prev.end());
            }
        }
        m[s] = res; // memorize

        return res;
    }
};

results matching ""

    No results matching ""