Leetcode 140. Word Break II

Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences.

Note:

The same word in the dictionary may be reused multiple times in the segmentation.
You may assume the dictionary does not contain duplicate words.
Example 1:

Input:
s = “catsanddog”
wordDict = [“cat”, “cats”, “and”, “sand”, “dog”]
Output:
[
“cats and dog”,
“cat sand dog”
]

method 1 backtracking

附上一个TLE的反面案例
超时的原因在于,许多子字符串的分割重复,每次传入的都是原来的字符串,再加上一个start指示开始索引
一般情况下都是可以通过的,但当遇到极端case诸如 aaaaaaaaaaaaaaa和[a,aa,aaa,aaaa,aaaaa]这样的,会导致大量的重复计算,最后导致超时
对于超时有两点体会

  1. 引入dp
  2. 每次传入时,传入新的截取过后的字符串,更容易分析
void helper(vector<string>& ans, string s, int start, vector<string>& wordDict, string tmp){
	if (start == s.size()){
		ans.push_back(tmp.substr(1, tmp.size() - 1));
	}
	else{
		for (int i = start; i < s.size(); i++)
		{
			string left = s.substr(start, i - start + 1);
			if (find(wordDict.begin(), wordDict.end(), left) != wordDict.end()){
				helper(ans, s, i + 1, wordDict, tmp + " " + left);
			}
		}
	}
}

vector<string> wordBreak(string s, vector<string>& wordDict) {
	vector<string> ans;
	if (wordDict.size() == 0) return ans;

	helper(ans, s, 0, wordDict, "");
	return ans;
}

method 2 dynamic programming

引入dp, 记录字符串s对应的所有句子,因为在回溯过程中,会出现重复的分支,在正常输入下,基本不会出现重复的分支,但比如aaaaaaaaa,[a,aa,aaa,aaaa]这样的,就会导致许多重复分支,所有使用dp记录下来,遇到合适的字符串,直接返回其ans

  1. 虽然自己用dp尝试过,但思路不对,只是简单想着某一个substr是否出现过,如果出现过,还是对其递归回溯,应该进一步想,如果出现过,直接记录其结果
  2. 没有找到重复最多的部分进行优化
  3. 画出解答树优化
unordered_map<string, vector<string>> m;

    vector<string> combine(string word, vector<string> prev){
        for(int i=0;i<prev.size();++i){
            prev[i]+=" "+word;
        }
        return prev;
    }
    
    vector<string> wordBreak(string s, vector<string>& wordDict) {
	if (m.count(s)) return m[s]; //take from memory
	vector<string> result;
	if (find(wordDict.begin(), wordDict.end(), s) != wordDict.end()){ //a whole string is a word
		result.push_back(s);
	}
	for (int i = 1; i<s.size(); ++i){
		string word = s.substr(i);
		if (find(wordDict.begin(), wordDict.end(), word) != wordDict.end()){
			string rem = s.substr(0, i);
			vector<string> prev = combine(word, wordBreak(rem, wordDict));
			result.insert(result.end(), prev.begin(), prev.end());
		}
	}
	m[s] = result; //memorize
	return result;
}

summary

  1. 递归回溯传入时,传入新的截取过后的字符串,更容易分析
  2. 要对重复最多的部分进行优化
  3. 可以选取TLE的case,画出解答树,从而找到重复最多的部分,正确的引入dynamic programming解决问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值