第十一周:[Leetcode]139. Word Break

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];
}
};
点赞