题目如下:
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];
}
};

本文介绍了如何解决LeetCode上的139题——Word Break,即给定一个字符串s和一个词典,判断s是否可以被分割成一个或多个词典中的单词。首先尝试使用递归方法,但因效率低下导致超时。接着分析问题,发现其具有动态规划性质,并详细阐述了动态规划的思路。通过从后往前考虑,如果字符串的每个子串在词典中存在,则原字符串可成功分割。最后,给出了两版代码实现。
1208

被折叠的 条评论
为什么被折叠?



