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"
.
分析:
方法一、暴力破解,从前往后扫描,找到第一个在dict中的单词a后,递归求解剩余的部分是否可拆分。如果找到解就结束。否则重新a后面添加元素来拆分。
思路比较清晰,但是对于长的串,超时。O(n^n)
代码:
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
int len=s.size();
if(len<1) return true;
bool res;
for(int j=1;j<=len;j++){
string t=s.substr(0,j);
unordered_set<string>::iterator it=dict.find(t);
if(it!=dict.end()){
res=wordBreak(s.substr(j),dict);
if(res) return res;//找到符合的分割,返回,否则继续往下找。
else continue;
}
}
return false;
}
};
方法二:在暴力的基础上剪枝,添加一个cannotmatch的set,用来记录之前无法在dict中找到的串。
代码:Accepted
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
if(s.length()<1) return true;
set<string> cannotmatch;
return wordBreakHelper(s,dict,cannotmatch);
}
bool wordBreakHelper(string s, unordered_set<string> &dict, set<string> &cannotmatch) {//剪枝cannotmatch
int len=s.size();
if(len<1) return true;
bool res;
for(int j=1;j<=len;j++){
string t=s.substr(0,j);
unordered_set<string>::iterator it=dict.find(t);
if(it!=dict.end()){
string partofs=s.substr(j);//出去匹配部分,剩余的串
set<string>::iterator it=cannotmatch.find(partofs);
if(it!=cannotmatch.end()) continue;//如果后边部分在不能匹配集合中,直接试探下一个长度
else{
res=wordBreakHelper(partofs,dict,cannotmatch);
if(res) return res;//找到符合的分割,返回,否则继续往下找。
else cannotmatch.insert(partofs);//如果partofs还是不能拆分,添加到我们的cannotmatch 集合中。
}
}
}
return false;
}
};
方法三:DP,题目看起来像dp,却想不清楚。google之。使用一个bool数组t[],t[i]表示0-(i-1)该字符串是否可拆分。最后返回t[len]即可。
i从0到len-1 开始遍历:时间复杂度O(n*m) n表示字符串长度,m表示字典单词数目。空间复杂度O(n)
- 如果t[i]为ture,说0-(i-1)部分可拆分,然后去遍历dict中的单词,是否是string s从i往后同长度可以得到的单词。
如果dict中存在这样的单词,对应所有的 true[i+len]=true;
如果所有的dict都没有,t[i]是默认的false。
代码:
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
if(s.length()<1) return true;
int len=s.length();
bool t[len+1];//={false};//t[i] 0-(i-1)是否可分 初始化为false
memset(t,0,len+1);
t[0]=true;//相当于空串"" 可拆分
for(int i=0;i<len;i++){
if(t[i]==false) continue;//如果0-(i-1)不可拆分,i之后的串即使可拆分,整个串也是不可拆分的。
unordered_set<string>::iterator it=dict.begin();
for(;it!=dict.end();it++){
string strdict=(*it);
int lenstr=strdict.length();
int end=i+lenstr;//可以达到的末尾下标
if(end > len) continue;//比源字符串 长
if(t[end]==true) continue;//本来就是true,直接继续扫描字典的下一个单词
if(s.substr(i,lenstr)==strdict){
t[end]=true;
}
}
}//for i
return t[len];
}
};