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