LeetCode - Word Break / Word Break II 题解

来源:互联网 发布:mac桌面下方图标隐藏 编辑:程序博客网 时间:2024/05/17 02:57

WordBreak

Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

For example, given
s = "leetcode",
dict = ["leet", "code"].

Return true because "leetcode" can be segmented as "leet code".

方法一,深搜(超时):

class Solution {public:    bool check(string s1,string s2){        if(s2.length() > s1.length() || s1.substr(0,s2.length()) != s2)            return false;        else            return true;    }    typedef unordered_set<string>::iterator iter;    bool found = false;    bool wordBreak(string s, unordered_set<string> &dict) {        if(s==""){            found = true;            return true;        }        for(iter it = dict.begin();it != dict.end();it++)        {            if(found) return true;            if(check(s,*it)){                int l = (*it).length();                if(wordBreak(s.substr(l,s.length() - l), dict)){                    return true;                }            }        }        return false;    }};

方法二,动态规划:

设f[i]代表用s[0]-s[i]的字符串是否能拼起来,则状态转移方程

f[i] = any(f[j] && s[j+1,i] ∈dict) (-1 <= j < i)

时间复杂度O(n^2)

class Solution {public:    bool wordBreak(string s, unordered_set<string> &dict) {        int l = s.length();        bool *f = (bool*)calloc(l,sizeof(bool));        for(auto x:dict)            if(x == s.substr(0,x.length())){                f[x.length() - 1] = true;            }        for(int i = 0; i < l; i++){            if(f[i]) continue;            for(int j = 0; j < i; j++){                if(f[j] && dict.find(s.substr(j+1,i-j)) != dict.end()){                    f[i] = true;                    break;                }            }        }        bool ans = f[l - 1];        delete f;        return ans;    }};

WordBreak II

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

分析:

比上题多了输出所有方案,只要在dp的过程中记一下中间结果即可。

g[i]表示s[g[i]+1,i]是dict里面的单词,在dp结束后,从S.length()-1位置可以往回一次找到每次划分出的单词。

注意到g[i]可能会有多种答案,g[i]所以是一个集合,g是元素为集合的数组。

class Solution {public:    vector<string> ans;    string ss;    vector<string> wordBreak(string s, unordered_set<string> &dict) {        ss = s;        int l = s.length();        bool *f = (bool*)calloc(l,sizeof(bool));        vector<unordered_set<int> > g(l);        for(auto x:dict)            if(x == s.substr(0,x.length())){                f[x.length() - 1] = true;                g[x.length() - 1].insert(-1);            }        for(int i = 0; i < l; i++){            for(int j = 0; j < i; j++){                if(f[j] && dict.find(s.substr(j+1,i-j)) != dict.end()){                    f[i] = true;                    g[i].insert(j);                }            }        }        string now = "";        trace_ans(l-1,g,now);        delete f;        return ans;    }    void trace_ans(int i,vector<unordered_set<int> > g,string now){        if(i == -1){            ans.push_back(now.substr(0,now.length() - 1));            return;        }        for(auto x:g[i])            trace_ans(x, g, ss.substr(x+1, i-x) + " " + now);    }};


0 0
原创粉丝点击