题目如下:
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".
分析如下:
题目意思是,给定词典的情况下,看看原字符串能不能全部成功地被给定的词典分割。一开始,最自然的想法是,使用递归。提交,超时了。想想,这个问题其实具有动态规划的特点。比如计算catsanddog的分割方式,那么倒着想如下:
到了最后一个字符g的时候,
如果能在g之前切一刀,也就是说,如果g在词典中以及catsanddo能够成功切分,那么原字符串就可以成功切分。
或者,如果能在og之前切一刀,也就是说,如果og在词典中以及catsandd能够成功切分,那么原字符串就可以成功切分。
或者,如果能在dog之前切一刀,也就是说,如果dog在词典中以及catsand能够成功切分,那么原字符串就可以成功切分。
或者,如果能在ddog之前切一刀,也就是说,如果ddog在词典中以及catsan能够成功切分,那么原字符串就可以成功切分。
或者,如果能在nddog之前切一刀,也就是说,如果nddog在词典中以及catsa能够成功切分,那么原字符串就可以成功切分。
或者,如果能在anddog之前切一刀,也就是说,如果anddog在词典中以及cats能够成功切分,那么原字符串就可以成功切分。
或者,如果能在sanddog之前切一刀,也就是说,如果sanddog在词典中以及cat能够成功切分,那么原字符串就可以成功切分。
或者,如果能在tsanddog之前切一刀,也就是说,如果tsanddog在词典中以及ca能够成功切分,那么原字符串就可以成功切分。
或者,如果能在atsanddog之前切一刀,也就是说,如果atsanddog在词典中以及c能够成功切分,那么原字符串就可以成功切分。
或者,如果能在catsanddog之前切一刀,也就是说,如果catsanddog在词典中以及""能够成功切分,那么原字符串就可以成功切分。
使用一个数组bool wordB[i] 来记录,在单词长度为i的时候,能否成功切分(i取值范围必然为[ 0, word.length() ] )
我的代码:
第一版
//第一版,递归超时 class Solution { public: bool wordBreak_(string s, unordered_set<string> &dict) { if(s.length()==0) return true; bool ret=false; if(s.length()){ std::cout<<"s="<<s<<std::endl; for(unordered_set<string>::iterator it =dict.begin();it!=dict.end();it++){ if(s.find(*it)==0){ bool small_ret=true; std::cout<<"small_ret->"<<*it<<std::endl; string tmp=s.substr((*it).length()); std::cout<<"tmp="<<tmp<<std::endl; small_ret=small_ret&&wordBreak_(tmp,dict); if(small_ret==false) continue; ret=ret||small_ret; if(ret==true) break; } } } return ret; } bool wordBreak(string s, unordered_set<string> &dict) { if(s.length()==0) return false; return wordBreak_(s,dict); } };
第二版
// 第二版 参考leetcode官网上的答案 class Solution { public: bool wordBreak(string s, unordered_set<string> &dict) { vector<bool> wordB(s.length() + 1, false); wordB[0] = true; for (int i = 1; i < s.length() + 1; i++) { for (int j = i - 1; j >= 0; j--) { if (wordB[j] && dict.find(s.substr(j, i - j)) != dict.end()) { wordB[i] = true; break; //只要找到一种切分方式就说明长度为i的单词可以成功切分,因此可以跳出内层循环。 } } } return wordB[s.length()]; } };
update: 2015-04-09
//16ms class Solution { public: bool wordBreak(string s, unordered_set<string> &dict) { vector<bool> result(s.length(), false); for (int i = 0; i < result.size(); ++i) { if (dict.find(s.substr(0, i + 1)) != dict.end()) { result[i] = true; continue; } for (int j = 0; j < i; ++j) { if ((result[j] == true) && (dict.find(s.substr(j + 1, i -j))!= dict.end())) { result[i] = true; break; } } } return result[result.size() - 1]; } };