Word Break


Word Break   Total Accepted: 4925 Total Submissions: 26611 My Submissions
 
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".

这个题最先想到就是回溯递归法,主要还是递归了,用回溯是因为最近在练习回溯方法,就用了回溯的框架算法,简单的写了下。

版本1.暴力回溯递归法,一般地,对于字符串,str[t...n]扫描,如果扫描到i,字典中有匹配的,那么递归对str[i+1,n]的字符串进行处理,如果扫描到i,t--i之间的字符串没有匹配的,则继续i++什么也不做。若不做任何剪枝,连一般的数据的都会timeout,所以优化第一步if(dirc.count(subs) && cou == 0)加了一个cou==0,如果搜索到结果了,就不找了,题中只要求是否存在解。

下面的这个算法,就是基本无优化的,所以很难过极限值,你可以提交试试,但对于一步步学习研究很有用啊,基础不好的,不是来就能想到优化策略的,先写出这个,然后慢慢优化。

 

class Solution {
    
int cou = 0;
vector<string> ve,re;
string str;
int n;
void BackTrack(int t,unordered_set<string>& dirc,int *a)
{
   if(t == n)
   {
        cou++;
       // re = ve;
   }else
   {
        for(int i = t; i < n; i++)
        {
                string subs = str.substr(t,i-t+1);
                //cout << "t " << t << " i " << i << " subs" << subs << endl;
                if(dirc.count(subs) && cou == 0)
                {
                   // cout << "t " << t << " subs" << subs << endl;
                   // ve.push_back(subs);                   
                    BackTrack(i+1,dirc,a);
                    
                       //    ve.pop_back();
                }
        }
   }
}
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        
        str = s;
        n = str.size();
        int *a = new int[n];
        for(int i = 0; i < n; i++)
        a[i] = 1;
        BackTrack(0,dict,a);
        delete [] a;
        if(cou) return true;
        else return false;
       
    }
};


版本2,是加了,记忆化搜索,也即,对于i之前已经匹配的搜索过程中,对于一个j>i,若str[j..end]无解,那么下次就不用搜索这个子字符串了,能直接进行判断,非常省力气。所以这里,添加了一个数组a,用来记录字符串中每一个i,到end,之间的字符串是否可以找到解,如果不能找到,那么下次再次递归到该子字符串时就不用搜索了。  不懂的话,推荐看刘汝佳那本白皮书,acm竞赛入门经典 ,动态规划那一章,讲到有记忆化搜索,非常好用!
下面这两行就是对上面的一个优化,只增加了两个判断,用于剪枝和维护数组a。
 if(((i+1) != n && a[i+1]) || i+1 == n)BackTrack(i+1,dirc,a);
                    if(!cou) a[i+1] = 0;

class Solution {
    
int cou = 0;
vector<string> ve,re;
string str;
int n;
void BackTrack(int t,unordered_set<string>& dirc,int *a)
{
   if(t == n)
   {
        cou++;
       // re = ve;
   }else
   {
        for(int i = t; i < n; i++)
        {
                string subs = str.substr(t,i-t+1);
                //cout << "t " << t << " i " << i << " subs" << subs << endl;
                if(dirc.count(subs) && cou == 0)
                {
                   // cout << "t " << t << " subs" << subs << endl;
                   // ve.push_back(subs);                   
                    if(((i+1) != n && a[i+1]) || i+1 == n)BackTrack(i+1,dirc,a);
                    if(!cou) a[i+1] = 0;
                       //    ve.pop_back();
                }
        }
   }
}
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        
        str = s;
        n = str.size();
        int *a = new int[n];
        for(int i = 0; i < n; i++)
        a[i] = 1;
        BackTrack(0,dict,a);
        delete [] a;
        if(cou) return true;
        else return false;
       
    }
};


 

3,本地测试整个文件代码

#include<iostream>
#include<string>
#include<vector>
#include<cstdlib>
#include<set>

using namespace std;
int cou;
vector<string> ve,re;
string str;
int n;
int a[10];
void BackTrack(int t,set<string>& dirc)
{
   if(t == n)
   {
        cou++;
        re = ve;
   }else
   {
        for(int i = t; i < n; i++)
        {
                string subs = str.substr(t,i-t+1);
                cout << "t " << t << " i " << i << " subs" << subs << endl;
                if(dirc.count(subs))
                {
                    cout << "t " << t << " subs" << subs << endl;
                    ve.push_back(subs);                   
                    if(a[i+1])BackTrack(i+1,dirc);
                    if(!cou)a[i+1] = 0;
                    ve.pop_back();
                }
        }
   }
}
int main()
{
    string  s[] =  {"a"}; 
    set<string> dirc(s,s+1); 
    str = "a";
    n = str.size();
    for(int i = 0; i < 10; i++)
    a[i] = 1;
    BackTrack(0,dirc); 
    for(vector<string>::iterator it = re.begin(); it != re.end(); it++)
    {
         cout << *it << " ";
    }
    cout << "cou " << cou << endl;
    system("pause");
    return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值