动态规划之Word Break详解

匿名 (未验证) 提交于 2019-12-03 00:29:01

之前刷LeetCode。碰到了这道题。

一开始没想到要用动态规划来解。

后来看了一下答案给的代码,又仔细研究了一下,发现确实是动态规划。

中途看了很多其他人的博客解释,都没把动态规划讲清楚。

所以干脆就自己来写一份详解吧。


首先,把题目贴上来

sdicts

For example, given
s"leetcode",
dict["leet", "code"].

"leetcode""leet code".


简单来说,就是s能不能由dict中存储的单词拼出来。

注意了,这里有陷阱。不能简单的从前往后substr递增的检查是否包含在dict中,否则会有问题。


下面开始介绍怎么用动态规划来讲。


该说的都说了,接下来到实际问题里面去体会。

先贴出官网给出的标准答案

bool wordBreak(string s, unordered_set<string> &dict) { 	vector<bool> flag(s.length()+1,false); 	flag[0] = true;  	for (int i = 1; i < s.length()+1; ++i) 	{ 		for (int j = i - 1; j >= 0; j--) 		{ 			if (flag[j] && dict.count(s.substr(j, i-j)) != 0) 			{ 				flag[i] = true; 				break; 			} 		} 	} 	return flag[s.length()]; }

简单讲一下这里是怎么利用动态规划的。

首先

vector<bool> flag(s.length()+1,false);

具体怎么做的等会再说。

这里的第一层 i 循环,其实就是我们刚才讲的1,也就是子问题。

你可以理解为 i 从1一直到s.length() ,分别表示从下标0开始,长度为1的子问题,长度为2的子问题,……,长度为s.length()的子问题。

而长度为s.length()的子问题的解,其实也就是原问题的解了。


现在再来解释flag数组。

if (flag[j] && dict.count(s.substr(j, i-j)) != 0) { 	flag[i] = true; 	break; }

并且有s.substr(j,i-1) 这个子串包含在 dict中。

这样,是不是就利用了前面 子问题i 的计算结果避免了重复计算 子问题i呢。

至此,整个动态规划的思想就讲完了。


我自己又写了一个递归版本的答案,如果你对上面的似懂非懂的话,可以参考一下我的答案。

vector<bool> *flag;  bool fun(string s, unordered_set<string> &dict, int i) { 	if (i == 0 && (*flag)[0] == false) 		return dict.find(s) != dict.end(); 	while (i > 0 && (dict.find(s.substr(i, s.length() - i)) == dict.end()||(*flag)[i]==true)) 	{ 		i--; 	} 	if (i == 0 && dict.find(s.substr(i, s.length() - i)) == dict.end()) 		return false; 	else 		if (i == 0) 			return true; 	(*flag)[i] = true; 	return fun(s.substr(0, i), dict, i-1) || fun(s, dict, i); }  bool wordBreak(string s, unordered_set<string> &dict) { 	if (s.length() == 0) 		return false; 	vector<bool> mflag(s.length(), false); 	flag = &mflag; 	return fun(s, dict, s.length()-1); }

简单给点提示,因为要递归,所以flag 数组需要放在全局变量。

最简单的解释就是看它的return语句。返回两个递归的结果。分别表示从后往前 s.length()-i长度的这个子串是答案的解或者它不是答案的解。(有时候s的子串包含在dict中但不是答案的解,见上面的 aaa aaa a 这种分法)

是解,或者不是解,包含了所有可能的情况。因此分成了两种子问题。再加上全局变量flag避免重复计算。

因此满足了动态规划的所有步骤。得到的也是正确答案。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!