139. Word Break

简单的动态规划问题,采用自顶向下的备忘录方法,代码如下:

class Solution {
public:
    bool dictContain(unordered_set<string> &dict, string s)
    {
        unordered_set<string>::iterator ite = dict.find(s);
        if(ite != dict.end())
            return true;
        else return false;
    }

    bool wordBreak(string s, unordered_set<string> &dict)
    {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        if(dict.empty())
            return false;
        const int len = s.size();
        bool canBreak[len]; //canBreak[i] = true 表示s[0~i]是否能break
        memset(canBreak, 0, sizeof(bool)*len);
        for(int i = 1; i <= len; i++)
        {
            if(canBreak[i-1] == false && dictContain(dict, s.substr(0, i)))
                canBreak[i-1] = true;

            if(canBreak[i-1] == true)
            {
                if(i == len)return true;
                for(int j = 1; j <= len - i; j++)
                {
                    if(canBreak[j+i-1] == false && dictContain(dict,s.substr(i, j)))
                        canBreak[j+i-1] = true;

                    if(j == len - i && canBreak[j+i-1] == true)return true;

                }
            }

        }

        return false;
    }


};
注意:在本机调试时,编译器要开启c++11支持,因为#include<unordered_set>是c++11的标准


9.18更新-------------

第一开始我做此题的时候,用了二维的DP,结果总是TLE。后来看了答案发现只用一维DP就可以了。

那为什么这里只用一维DP就行了呢,因为...... 因为.... 因为起点和终点都是确定的!!!!正因为起点和终点都是确定的,所以我们没有必要进行二维DP,平白无故地浪费了大量的时间复杂度!!!

另外,需要注意,上面的解法和下面的解法是不同的!!!!,上面的解法是先找到一个从0开始的到i可以break的子串,然后再从i+1开始向后搜索,看能不能形成更大的可以break的子串。而第二种解法是对一个从0到i的子串,通过判断它的前半部分是否可以break并且后半部分是否在wordDict,来决定这个从0到i的子串是否可以break。通过比较发现,前面的那个方法,侧重于向串的后面进行搜索,后面的方法侧重于向串的前面进行搜索。(这里的前,指的是下标越来越大。)

思路:Word Break I

看到这题第一反应是DFS枚举查找,直到“探”到string尾部则算成功。但题目并不要求给出是如何break的,而只要判断是否能break。对这类判断“是”与“否”的可以用DFS暴力解决的题,可以尝试用DP做book keeping中间判断状态,避免DFS的反复搜索。比如这题,可以用一个数组dp记录S[0:i]是否能break。

dp[i]:S[0:i-1]是否能被break。例如dp[1]表示s[0]是否能被break。
dp[0] = true
dp[i] = true if and only if:
1. 存在一个i-1>=k>=0,使s[k:i-1]存在于dict中。
2. s[0: k-1]可以被break,即dp[k] = true。

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值