LeetCode - Word Break / Word Break II 题解

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值