[leetcode]Word Break


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

 转载请注明原创:http://www.cnblogs.com/StartoverX/p/4604668.html

  分析:输入是一个unordered-set<string>& wordDict,一个string& s,输出是一个bool值,判断string s是否能被分解成wordDict中的string值。

  分析该问题我们发现,如果s能够被分解成wordDict中的单词组合,那么,对于其分割答案中的一次分割s->s1,s2,将s分割成s1和s2,s1和s2必也能分割成wordDict中的单词。也就是对s的分割包含了对s1和s2的分割,该问题的最优解包含了其子问题的最优解,该问题具有最优子结构性质。

  现在我们可以尝试通过递归的方法求解该问题,我们对于s中每两个字符间的每一次分割遍历s,如果分割得到的s1和s2都能被分解为wordDict中的单词,我们就说s能够被分解为wordDict中的单词,如果s1和s2不能被分解为wordDict中的单词,则继续遍历s。如果分割点直到s中的最后一个字符都没能得到两个都能被分解的s1和s2,则我们说s不能分解为s1和s2中的单词。

#include <iostream> #include <vector> #include <string> #include <unordered_set> #include <algorithm>
using namespace std; class Solution { public: bool wordBreak(string s,unordered_set<string>& wordDict) { if(wordDict.size() == 0) //边界条件1
 { return false; } if(s.size() == 0) //边界条件2
 { return false; } if(find(wordDict.begin(),wordDict.end(),s) != wordDict.end()) //递归退出条件
 { return true; }      int size = s.size(); if(size == 1) //如果wordDict中没找到s,s又不能继续分割,return false
 { return false; } for(int i=1;i<size;i++) //对s遍历每一个分割点
 { string s1 = s.substr(0,i); string s2 = s.substr(i,size); if(wordBreak(s1,wordDict) && wordBreak(s2,wordDict)) { return true; } } return false; } };

  分析上述递归的方法,我们发现,对于每一个s,我们都要遍历它的每两个字符间的分割点,而s分割出来的s1,s2,又包含了同样的字符顺序,也就是,我们重复求解了很多次相通的字符串,所以,上面的递归解法非常的低效。由于我们判断出该题的子问题相互重叠,我们使用动态规划的方法。

  上面已经得到了一个递归解法,所以在动态规划解法中我们使用带备忘的自顶向下法对于此问题,我们要求的解是对于一个特定的string,求对应的bool值,所以我们使用一个全局map:map<string,bool> mp来保存每次的结果。在每次递归前检查是否已经取得了解,并在递归后在map中保存解。

#include <iostream> #include <vector> #include <string> #include <unordered_set> #include <algorithm> #include <map>
using namespace std; class Solution { public: map<string,bool> mp; bool wordBreak(string s,unordered_set<string>& wordDict) { if(wordDict.size() == 0) //边界条件1
 { return false; } if(s.size() == 0) //边界条件2
 { return false; } if(find(wordDict.begin(),wordDict.end(),s) != wordDict.end()) //递归退出条件
 { return true; } int size = s.size(); if(size == 1) //如果wordDict中没找到s,s又不能继续分割,return false
 { return false; } for(int i=1;i<size;i++) //对s遍历每一个分割点
 { string s1 = s.substr(0,i); string s2 = s.substr(i,size); bool flag1 = false; bool flag2 = false; bool is1 = false; bool is2 = false; if(mp.empty() == false && (mp.find(s1) != mp.end()))//如果已经得到了s1的解,直接从mp中取。
 { is1 = true; flag1 = (*mp.find(s1)).second; } if(mp.empty() == false && (mp.find(s2) != mp.end()))//如果已经得到了s2的解,直接从mp中取。
 { is2 = true; flag2 = (*mp.find(s2)).second; } if(is1 == false)//如果没有得到过s1的解,求解并保存在mp中。
 { flag1 = wordBreak(s1,wordDict); mp[s1] = flag1; } if(is2 == false)//如果没有得到过s2的解,求解并保存在mp中。
 { flag2 = wordBreak(s2,wordDict); mp[s2] = flag2; } if(flag1 && flag2) { return true; } } return false; } };

 

你可能感兴趣的:(LeetCode)