字符串单词拆分 Word Break

142 篇文章 20 订阅
45 篇文章 0 订阅

问题一(判断能否进行单词拆分):给出一个字符串,问能否将其拆分为1或多个单词。单词表已给出。

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".


思路:直观思路是递归尝试进行。但是超时。注意,递归尝试往往会重复把一件已经做过的事情做很多次。

而另外一个算法,动态规划,则是借助空间暂存结果,待到下次需要用的时候直接拿结果。这是递归和DP的重要区别。

递归和DP的重要相同点是,都存在子问题。

这道题用动态规划算法的话,会变得非常的快。


状态量H[i],表示字符串s的前i个字符组成的子串是否能够进行单词拆分。

递推关系:k from 0 to i-1,只要有一个k满足 H[k]==1 且 s[k...i-1]是一个单词。则表明H[i]是比H[k]多加了一个单词,因此H[i]等于1.

class Solution {
	public:
		bool wordBreak(string s, unordered_set<string> &dict) {

			int n = s.size();
			if(n ==0)
				return false;
			int H[n+1];//H[i]表示s中前i个字符是否能进行word break
			memset(H,0,sizeof(H));
			H[0] = 1;
			for(int i=1;i<=n;i++)
			{
				for(int j=0;j<i;j++)
					if(H[j] == 1 && dict.find(s.substr(j,i-j)) != dict.end())
					{
						H[i] = 1;
						break;
					}
			}
			return (H[n]==1);
		}
};


问题二(进行单词拆分):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"].


 思路:首先利用上面的动态规划方法判断能否进行拆分。然后利用backtrack方法生成所有组合。

class Solution {
public:
    vector<string> wordBreak(string s, unordered_set<string> &dict) {
        vector<string> re;
        int n = s.size();
        if(n == 0)
            return re;
        
        int H[n+1];
        memset(H, 0, sizeof(H));
        H[0] = 1;
        for(int i=1; i<=n;i++)
        {
            for(int j=0;j<i;j++)
            {
                if(H[j] == 1 &&  dict.find(s.substr(j, i-j)) != dict.end() )
                {
                    H[i] = 1;
                    break;
                }
            }
        }
        
        if(H[n] == 0) // 先利用DP方法检验是否能够拆分单词
            return re;
        string now = "";
        backtrack(s, now, 0, H, n, dict, re); //再用backtrack方法进行组合生成
        return re;
    }
    
    void backtrack(string &s, string &now, int idx, int H[], int n, unordered_set<string> &dict, vector<string> &re)
    {
        if(idx == n)
        {
            re.push_back(now);
            return;
        }
        for(int i=idx;i<n;i++)
        {
            if(H[i+1] == 1 && dict.find(s.substr(idx, i-idx+1)) != dict.end() )
            {
                string new_now;
                if(now == "")
                    new_now = s.substr(idx, i-idx+1);
                else
                    new_now = now + " " + s.substr(idx, i-idx+1);
                backtrack(s, new_now, i+1, H, n, dict, re);
            }
        }
    }
    
};


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值