LeetCode 题解(9):Word Break

题目:

Given a string s and a dictionary of wordsdict, determine ifs 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> &dict) {
        a = new int*[s.length()];
        for(int i = 0; i < s.length(); i++)
        {
            a[i] = new int[s.length()];
            for(int j = 0; j < s.length(); j++)
            {
                a[i][j] = 0;
            }
        }
        return wordBreak(s, dict, 0, s.length()-1);
    }
    
    bool wordBreak(string s, unordered_set<string> &dict, size_t start, size_t end)
    {
        if(a[start][end] == 1)
            return true;
        if(a[start][end] == -1)
            return false;
        string temp = s.substr(start, end-start+1);
        if(dict.find(temp) != dict.end())
        {
            a[start][end] = 1;
            return true;
        }
        
        for(size_t i = start; i < end; i++)
        {
            if(wordBreak(s, dict, start, i) && wordBreak(s, dict, i+1, end))
            {
                a[start][end] = 1;
                return true;
            }
        }
        a[start][end] = -1;
        return false;
    }
    
private:
    int** a;

};

解法二:自底向上动态规划,由判断第一个字符是否可查找逐次增加到全字符串。

class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        vector<bool> results(s.length()+1, false);
        results[0] = true;
        
        for(size_t i = 1; i <= s.length(); i++)
        {
            for(size_t j = 0; j < i; j++)
            {
                if(results[j] && dict.find(s.substr(j, i-j)) != dict.end())
                {
                    results[i] = true;
                }
            }
        }
        
        return results[s.length()];
    }

};

解法三:创建单词的trie树。

class Node {
public:
    bool end;
    Node* next[26];
    
    Node():end(false) {
        for(int i = 0; i < 26; i++)
        {
            next[i] = NULL;
        }
    }
    
    ~Node() {
        for(int i = 0; i < 26; i++)
        {
            delete next[i];
        }
    }
    
    void insert(string s) {
        Node* cur = this;
        for(size_t i = 0; i < s.length(); i++)
        {
            if(cur->next[s[i]-'a'] == NULL)
            {
                cur->next[s[i]-'a'] = new Node();
            }
            cur = cur->next[s[i]-'a'];
        }
        cur->end = true;
    }
    
};

class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        Node root;
        vector<bool> results(s.length(), false);
        for(unordered_set<string>::iterator iter = dict.begin(); iter != dict.end(); iter++)
        {
            root.insert(*iter);
        }
        
        testWord(s, &root, results, 0);
        
        for(size_t i = 0; i < s.length(); i++)
        {
            if(results[i])
            {
                testWord(s, &root, results, i+1);
            }
        }
        
        return results[s.length()-1];
        
    }
    
    void testWord(string s, Node* root, vector<bool> & results, size_t start)
    {
        Node* cur = root;
        for(size_t i = start; i < s.length(); i++)
        {
            if(cur->next[s[i]-'a'] != NULL)
            {
                if(cur->next[s[i]-'a']->end == true)
                {
                    results[i] = true;
                }
                cur = cur->next[s[i]-'a'];
            }
            else break;
        }
    }
    
};

2015-2-5日重做,忘记了动态规划,不过用unordered_map实现了类似的功能:

class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        if(!s.length() || !dict.size())
            return false;
        
		unordered_map<string, bool> trace;

		if(dict.find(s) != dict.end())
			return true;
        
		for(int i = 0; i < s.length(); i++) {
            string left = s.substr(0,i+1);
            string right = s.substr(i+1, s.length()-i-1);
            if(inDictRecurse(dict, left, trace) && inDictRecurse(dict, right, trace))
                return true;
        }
        return false;
    }
    
    bool inDictRecurse(unordered_set<string> &dict, string &s, unordered_map<string, bool> &trace) {
        if(!s.length())
            return true;

		if(trace.find(s) != trace.end())
			return trace.find(s)->second; 
			
        auto got = dict.find(s);
        if(got == dict.end()) {
            if(s.length() == 1) {
				trace.insert(pair<string, bool>(s, false));
				return false;
			}
			trace.insert(pair<string, bool>(s, false));
			for(int i = 0; i < s.length(); i++) {
                string left = s.substr(0,i+1);
                string right = s.substr(i+1, s.length()-i-1);

                if(inDictRecurse(dict, left, trace) && inDictRecurse(dict, right, trace))
                    return true;
            }
            return false;
        } else {
            return true;
        }
    }
};

网上重温了一下动态规划,时间要比递归短:

class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        if(!s.length() || !dict.size())
            return false;
        
        vector<bool> result(s.length() + 1, false);
        result[0] = true;
        
        for(int i = 1; i < s.length() + 1; i++) {
            for(int j = 0; j < i; j++) {
                result[i] = result[j] && (dict.find(s.substr(j, i-j)) != dict.end());
                if(result[i])
                    break;
            }
        }
        
        return result[s.length()];
    }
};

Java版:

public class Solution {
    public boolean wordBreak(String s, Set<String> dict) {
        if(s.length() == 0 || dict.size() == 0)
            return false;
        
        boolean[] result = new boolean[s.length()+1];
        result[0] = true;
        
        for(int i = 1; i < s.length()+1; i++) {
            for(int j = 0; j < i; j++) {
                result[i] = result[j] && (dict.contains(s.substring(j, i)) == true);
                if(result[i] == true)
                    break;
            }
        }
        
        return result[s.length()];
    }
}

Python版:

class Solution:
    # @param s, a string
    # @param dict, a set of string
    # @return a boolean
    def wordBreak(self, s, dict):
        if len(s) == 0 or len(dict) == 0:
            return False
        
        l = [False for x in range(0, len(s)+1)]
        l[0] = True
        
        for i in range(1,len(l)):
            for j in range(0,i):
                l[i] = l[j] and (s[j:i] in dict)
                if l[i] == True:
                    break
                
        return l[len(s)]


你可能感兴趣的:(Algorithm,LeetCode,WordBreak)