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"
.
方案一:递归进行搜索,超时
思路:s中第index开始向后找,当到i匹配成功后,再递归判断i...n是否匹配,如果不匹配就判断index...i+1等等。递归进行。
我实现的方案当中,当找到了某一个关键词了,就在集合中删去该关键词,也就是关键词只能用一次。但网上都没有这么做,证明可以使用多次。
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
if(s.size() == 0)
return true;
return FindBreak(s,0,dict);
}
bool FindBreak(string s,int index,unordered_set<string> dict){
if(index >= s.size())
return true;
for(int i = 1;index+i<=s.size();i++){
string word = s.substr(index,i);
if(dict.find(word) != dict.end()){
dict.erase(word);
bool flag = FindBreak(s,index+i,dict);
if(flag)
return true;
dict.insert(word);
}
}
return false;
}
};
方案二:
既然暴力搜索超时,那么就想更优化的方案,其中动态规划是挺容易想到的,能解决多次重复的问题。
当我们找0...i+1时,前面是否匹配已经求好,那么a[i+1] = map.find(0....i+1) || (a[j] && map.find(j+1...i+1))。其中j从0到i。也就是看能否有0...j和j+1...i+1拼接成。
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
int nsize=s.size();
int i=0,j=0;
bool *dp = new bool[nsize];
memset(dp,false,sizeof(dp));
for(i=0;i<nsize;++i)
{
dp[i] = ((dict.find(s.substr(0,i+1))!=dict.end())?true:false);
if(dp[i])
continue;
else
{
for(j=0;j<i;++j)
{
if(dp[j])
{
dp[i] = ((dict.find(s.substr(j+1,i-j))!=dict.end())?true:false) | dp[i];
}
}
}
}
return dp[nsize-1];
delete []dp;
}
};