[LeetCode] [动态规划] Word Break

来源:互联网 发布:电脑什么拍照软件 编辑:程序博客网 时间:2024/05/19 13:57

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

问题描述:给定一个字符串s和一个由单词组成的字典dict,判断是否能够将s分段成一个或者多个字典中的单词。

对于s,可以有很多种进行分段的方式,如果在这些分段方式中至少有一种情况:被截断的各个部分都是dict中的单词,那么,s就能够分段成一个或者多个字典中的单词。因此,最简单的想法是,如果能够得到一个单词的所有分段形式,然后遍历这些分段序列,直到有一种分段情况下,所有的单词都是dict中的单词,那么,就返回true,没有找到,就返回false。当然,这种方法是不现实的。

为了判断,就必须进行分段。首先,将[beg, end)引用的字符串分成[beg, sep)和[sep, end),sep必须从beg+1一直到end,如果其中有一种情况,两个区间的字符串可以进行分段,那么[beg, end)就可以进行分段。然后就需要递归判断两个字符串是否可以进行分段。但是只能对[beg, sep)和[sep, end)中的一个使用递归的判断函数,因为,这样做复杂度太高,因此,只对[sep, end)使用递归的判断函数,对[beg, sep)使用dict来判断。于是有下面的代码:

bool word(string::iterator beg, string::iterator end,unordered_set<string> &dict) {if(beg == end) {return true;}if(dict.find(string(beg, end)) != dict.end()) {return true;}string::iterator sep = beg + 1;while(sep != end) {if(dict.find(string(beg, sep)) != dict.end() && word(sep, end, dict)) {return true;}++sep;}return false;}bool wordBreak(string s, unordered_set<string> &dict){if(s.empty())return false;return word(s.begin(), s.end(), dict);}

提交的结果是:

TIme Limit Exceeded

超时了,说明算法的时间复杂度还是太高了,要设法进行优化。当进行递归时,如果分支中重复的分支很多,就可以使用动态规划。在判断[sep, end)时,使用了递归函数word,但是,如果对一个字符串进行考察可以知道,其中有很多重复判断,因此,必须减少重复判断,也就是增加记忆功能,将已经判断失败的字符串保存起来,当判断一个字符串时,可以先与失败的字符串比较,如果是失败的字符串,就继续下一轮判断,这样,可以加快判断。

class Solution {public:    bool word(string::iterator beg, string::iterator end, unordered_set<string> &dict, set<string> ¬_seg){if(beg == end)return true;if(dict.find(string(beg, end)) != dict.end()) {return true;}string::iterator sep = beg + 1;while(sep != end) {if(dict.find(string(beg, sep)) != dict.end() && dict.find(string(sep, end)) != dict.end()) {return true;}if(dict.find(string(beg, sep)) != dict.end()) {if(not_seg.find(string(sep, end)) == not_seg.end()) {if(word(sep, end, dict, not_seg)) {return true;}else {not_seg.insert(string(sep, end));}}}++sep;}not_seg.insert(string(beg, end));return false;}bool wordBreak(string s, unordered_set<string> &dict){if(s.empty())return false;set<string> not_seg;return word(s.begin(), s.end(), dict, not_seg);}};


0 0