Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words. You may assume the dictionary does not contain duplicate words.
For example, given
s = “leetcode”,
dict = [“leet”, “code”].
Return true because “leetcode” can be segmented as “leet code”.
解法一:dfs。将被匹配的字符串不断向下深度优先搜索,判断当前子串是否出现在字典中。直接暴力dfs会超时,使用一个bool数组p来记录dfs过程中未匹配长度的状态以及一个最小匹配长度(字典中最短值的长度),这样可以减少递归深度以及不必要的递归状态。为方便过程中在字典中寻找子串,将字典存储在了set中。
class Solution {
public:
bool dfs(string s,set<string>& dict,int unmatch_length,int min_match_length,vector<bool>& p){
if(unmatch_length < min_match_length)
return false;
int start_index = s.length() - unmatch_length;
if(p[start_index] == false)
return false;
if(dict.find(s.substr(start_index,unmatch_length)) != dict.end())
return true;
for(int i = 1;i <= unmatch_length;i++){
if(dict.find(s.substr(start_index,i)) != dict.end() && (unmatch_length - i >= min_match_length)){
if(dfs(s, dict, unmatch_length - i,min_match_length,p))
return true;
}
}
p[start_index] = false;
return false;
}
bool wordBreak(string s, vector<string>& wordDict) {
if(wordDict.size() < 1)
return false;
set<string> dict;
set<string> :: iterator itr = dict.begin();
int min_match_length = wordDict[0].size();
for(int i = 0; i < wordDict.size();i++){
min_match_length = min_match_length > wordDict[i].length() ? wordDict[i].length() : min_match_length;
dict.insert(itr,wordDict[i]);
}
if(dict.find(s) != dict.end())
return true;
vector<bool> p(s.length(),true);
return dfs(s,dict,s.length(),min_match_length,p);
}
};
解法二:动态规划。dp[i]表示字符串下标小于等于i的子串是否能被字典分割,若在下标i与j之间的单词在字典中出现(i>j),而dp[j]为真,则dp[i]也为真。可得状态转移方程:dp[i] = dict.find(ij之间的子串) &&dp[j]。
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
if(wordDict.size() < 1)
return false;
vector<bool> dp(s.length() + 1,false);
set<string> dict;
set<string> :: iterator itr = dict.begin();
for(int i = 0; i < wordDict.size();i++)
dict.insert(itr,wordDict[i]);
if(dict.find(s.substr(0,1))!= dict.end())
dp[0] = true;
else
dp[0] = false;
for(int i = 1;i <= s.length();i++)
for(int j = i;j >= 0;j--){
string sub = s.substr(j,i - j + 1);
if(dict.find(sub) != dict.end() && (j > 0 && dp[j - 1] || j == 0)){
dp[i] = true;
break;
}
}
return dp[s.length() - 1];
}
};