算法 之 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".

题目理解:

Trail1:

首先想到的是贪心的算法,可是直接就能举出反例:

比如:S = “aaaaa”

dict = [ ''aaaa"  , " aaa" , "aa"]

 显然,贪心是不对的,因此还没开始编代码就已经被否决了。


Trail 2:

对于字符串S,枚举取出S的 i-length 前缀,如果是字典中的词的话,那么对剩下的 S.size() - i 个字符递归调用该函数即可,代码如下:

        /*if(s.empty())return false;
        bool label = false;
        bool *labels = new bool[s.size()];
       // labels[0] = false;
        
        for(int i = 1; i < s.size() ; ++i)
        {
            string temp = s.substr(0,i);
            if(dict.find(temp) != dict.end())
            {
                string temp = s.substr(i);
                label = wordBreak(temp,dict);
            }
            if(label)break;
        }
        return label;


算法的思想是正确的,但是时间复杂度太高,导致在leetcode上面不能通过,因为其中重复计算了很多部分。

比如对于S的任何一个 i-length 前缀    和 j-length 前缀,不是一般性,假设 i < j ,  那么在判断 j-length 前缀的时候是存在重复计算 i-length 前缀的,然后 i-length前缀在前面已经计算过了,但是却没有保存下来。因此需要使用数组保存已经计算过的问题。因此DP就是很自然的事儿了。


Trail 3:

定义labels[ i ]  表示数组的前 i-length前缀是否可以拆成字典中的词。那么很显然的有:


labels[ i ]   =    1    如果存在  labels[ j ]  && ( S[ j +1, i ] 是否在dict中)     ( 0 < j  <= i )

否则就为0.

因此代码如下:

        if(s.empty())return false;
        bool label = false;
        bool *labels = new bool[ s.size() + 1 ];
        
        for(int i = 0 ; i < s.size() + 1; ++i)
            labels[i] = false;
            
        labels[0] = true;
        
        for(int i = 1 ; i <= s.size(); ++i)
        { 
            for(int j = 0; j < i ; ++j)
            {
                //bool label1 = labels[j];
                string s2 = s.substr(j,i-j);
                //bool label2 = false;
                //if(s2.empty() || (!s2.empty() && dict.find(s2) != dict.end()))
                if(dict.find(s2) != dict.end() && labels[j])
                    //label2 = true;
                    
                //if(label1 && label2)
                    labels[i] = true;
            }
        }
        return labels[s.size()];
        

因此,问题得解。

总结:多谢另一半的提醒,重复计算这个问题确实是很严重,我在计算机上测试过,相差的时间挺大。

另外,DP一直是我的一个弱项,推荐给大家之前我转载过的一篇文章,背包问题的,这个是DP的一个超级经典的应用。


http://blog.csdn.net/xuqingict/article/details/18766029

非常不错的文章,百读不厌!!!




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值