您的位置:首页 > 其它

139. Word Break

2016-11-26 20:47 190 查看
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”.

第一种方法:回溯法

开始我用穷举,这样毫不意外的超时,因为有太多重复递归了

class Solution {
public:
bool wordBreak(string s, unordered_set<string>& wordDict)
{
if(s.size()==0||wordDict.size()==0)
return false;
return helper(s,wordDict);
}
bool helper(string s, unordered_set<string>& wordDict)
{
if(s.size()==0)
return true;
if(wordDict.find(s)!=wordDict.end())
return true;
for(int i=1;i<s.size();i++)
{
string s1=s.substr(0,i);
string s2=s.substr(i);
bool left=wordDict.find(s1)!=wordDict.end();
bool right=wordDict.find(s2)!=wordDict.end();
if(left&&right)
return true;
else if(!left&&right&&helper(s1,wordDict))
return true;
else if(left&&!right&&helper(s2,wordDict))
return true;
else if(helper(s1,wordDict)&&helper(s2,wordDict))
return true;
}
return false;
}
};


改进方法:将不符合条件的子字符串放在存储起来,这样就不会重复递归调用了。

class Solution {
private:
unordered_set<string> fail;
bool dfs(string s, unordered_set<string>& wordDict) {
if (s.length() == 0)
return true;
for (int i = 1; i <= s.length(); i++) {
string a = s.substr(0, i);

if (wordDict.find(a) != wordDict.end()) {
string after = s.substr(i);
if (fail.find(after) == fail.end()) {
if (dfs(after, wordDict))
return true;
else
fail.insert(after);
}
}
}

return false;
}
public:
bool wordBreak(string s, unordered_set<string>& wordDict)
{
return dfs(s, wordDict);
}
};


还有一种改进方法类似,但是它是将不符合条件的子字符串的首位下标存储起来

//Use a set to record all position that cannot find a match in dict. That cuts down the run time of DFS to O(n^2)
class Solution {
public:
bool wordBreak(string s, unordered_set<string>& wordDict)
{
if(wordDict.size()==0)
return false;
unordered_set<int>fail;
return helper(s,wordDict,0,fail);
}
bool helper(string s, unordered_set<string>& wordDict,int index,unordered_set<int> &fail)
{
if(index==s.size())//基本情况
return true;
if(fail.find(index)!=fail.end())//记忆检查
return false;
//递归
for(int i=index+1;i<=s.size();i++)
{
string temp=s.substr(index,i-index);
if(wordDict.find(temp)!=wordDict.end())
{
if(helper(s,wordDict,i,fail))
return true;
else
fail.insert(i);
}
}
fail.insert(index);
return false;
}
};


第二种方法是使用动态规划,用match[i],代表s.sustr(0,i)是否是由字典组成的。

如果s.substr(j,i-j+1)是字典中的单词且match[j]是true,那么match[i]也是true。

class Solution {
public:
bool wordBreak(string s, unordered_set<string>
4000
& wordDict)
{
if(s.size()==0||wordDict.size()==0)
return false;
int length=s.length();
vector<bool>match(length+1,false);
match[0]=true;
for(int i=1;i<=length;i++)
for(int j=i-1;j>=0;j--)
{
if(wordDict.find(s.substr(j,i-j))!=wordDict.end())
{
if(match[j])
{
match[i]=true;
break;
}
}
}
return match[length];
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  回溯 动态规划