Leetcode: Word Break

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 wordBreak(string s, unordered_set<string> &dict) {
        string str1, str2;
        for (int i = s.size() - 1; i >= 0; --i) {
            str1 = s.substr(0, i+1);
            str2 = s.substr(i+1);
            if (str1.empty() || dict.find(str1) != dict.end()) {
                if (str2.empty() || dict.find(str2) != dict.end()) {
                    return true;
                }
                else {
                    if (wordBreak(str2, dict)) {
                        return true;
                    }
                }
            }
        }
        
        return false;
    }
};
怎么办呢?每次调用workBreak应该可以利用以前计算的结果,正是DP,通过。

class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        int size = s.size();
        int **dp = new int*[size];
        for (int i = 0; i < size; ++i) {
            dp[i] = new int[size];
            memset(dp[i], 0, sizeof(int)*size);
        }
        
        return wordBreakUtil(dict, dp, s, 0, size - 1);
    }
    
    bool wordBreakUtil(unordered_set<string> &dict, int **dp, string &s, int start, int end) {
        if (start > end) {
            return true;
        }
        
        string str1, str2;
        for (int i = end; i >= start; --i) {
            str1 = s.substr(start, i - start + 1);
            str2 = s.substr(i+1);
            if (dict.find(str1) != dict.end()) {
                dp[start][i] = 1;
                if (str2.empty()) {
                    return true;
                }
                else if (dict.find(str2) != dict.end()) {
                    dp[i+1][end] = 1;
                    return true;
                }
                else {
                    if (dp[i+1][end] == 0) {
                        if (wordBreakUtil(dict, dp, s, i + 1, end)) {
                           return true;
                       }
                       else {
                           dp[i+1][end] = -1;
                       }
                    }
                }
            }
            else {
                dp[start][i] = -1;
            }
        }
        
        return false;
    }
};
两维DP,空间用的比较多,在讨论区看到一个简单些的,用一维DP - dp[i]表示i之后的字符串是否可解。

class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        int len = s.length();
        vector<bool> dp(len + 1,false);
        dp[len] = true;

        for (int i = len - 1; i >= 0; --i) {
            for (int j = i; j < len; ++j) {
                string str = s.substr(i, j - i + 1);
                if (dict.find(str) != dict.end() && dp[j + 1]) {
                    dp[i] = true;
                    break;
                }
            }
        }
        
        return dp[0];
    }
};

================= 第二次==============

DP,有点类似求回文的思想,一开始用了两维的数组来保存状态。

class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        int size = s.size();
        vector<vector<bool>> breaks(size, vector<bool>(size, false));
        for (int i = size - 1; i >= 0; --i) {
            for (int j = i; j < size; ++j) {
                if (dict.find(s.substr(i, j-i+1)) != dict.end()) {
                    breaks[i][j] = true;
                    if (j + 1 >= size || breaks[j+1][size-1]) {
                        breaks[i][size-1] = true;
                        break;
                    }
                }
            }
        }
        
        return breaks[0][size-1];
    }
};


其实呢,一维就够了,只保存某个字符之后的字符串是否可解。

class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        int size = s.size();
        vector<bool> breaks(size, false);
        for (int i = size - 1; i >= 0; --i) {
            for (int j = i; j < size; ++j) {
                if (dict.find(s.substr(i, j-i+1)) != dict.end()) {
                    if (j + 1 >= size || breaks[j+1]) {
                        breaks[i] = true;
                        break;
                    }
                }
            }
        }
        
        return breaks[0];
    }
};

一年之后,还是想半天。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值