题目:
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()]; } };
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()]; } }
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)]