Given a string s and a dictionary of words dict, determine if s 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) {
string str1, str2;
for (int i = s.size() - 1; i >= 0; --i) {
str1 = s.substr(0, i+1);
str2 = s.substr(i+1);
if (str1.empty() || dict.find(str1) != dict.end()) {
if (str2.empty() || dict.find(str2) != dict.end()) {
return true;
}
else {
if (wordBreak(str2, dict)) {
return true;
}
}
}
}
return false;
}
};
怎么办呢?每次调用workBreak应该可以利用以前计算的结果,正是DP,通过。
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
int size = s.size();
int **dp = new int*[size];
for (int i = 0; i < size; ++i) {
dp[i] = new int[size];
memset(dp[i], 0, sizeof(int)*size);
}
return wordBreakUtil(dict, dp, s, 0, size - 1);
}
bool wordBreakUtil(unordered_set<string> &dict, int **dp, string &s, int start, int end) {
if (start > end) {
return true;
}
string str1, str2;
for (int i = end; i >= start; --i) {
str1 = s.substr(start, i - start + 1);
str2 = s.substr(i+1);
if (dict.find(str1) != dict.end()) {
dp[start][i] = 1;
if (str2.empty()) {
return true;
}
else if (dict.find(str2) != dict.end()) {
dp[i+1][end] = 1;
return true;
}
else {
if (dp[i+1][end] == 0) {
if (wordBreakUtil(dict, dp, s, i + 1, end)) {
return true;
}
else {
dp[i+1][end] = -1;
}
}
}
}
else {
dp[start][i] = -1;
}
}
return false;
}
};
两维DP,空间用的比较多,在讨论区看到一个简单些的,用一维DP - dp[i]表示i之后的字符串是否可解。
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
int len = s.length();
vector<bool> dp(len + 1,false);
dp[len] = true;
for (int i = len - 1; i >= 0; --i) {
for (int j = i; j < len; ++j) {
string str = s.substr(i, j - i + 1);
if (dict.find(str) != dict.end() && dp[j + 1]) {
dp[i] = true;
break;
}
}
}
return dp[0];
}
};
================= 第二次==============
DP,有点类似求回文的思想,一开始用了两维的数组来保存状态。
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
int size = s.size();
vector<vector<bool>> breaks(size, vector<bool>(size, false));
for (int i = size - 1; i >= 0; --i) {
for (int j = i; j < size; ++j) {
if (dict.find(s.substr(i, j-i+1)) != dict.end()) {
breaks[i][j] = true;
if (j + 1 >= size || breaks[j+1][size-1]) {
breaks[i][size-1] = true;
break;
}
}
}
}
return breaks[0][size-1];
}
};
其实呢,一维就够了,只保存某个字符之后的字符串是否可解。
class Solution {
public:
bool wordBreak(string s, unordered_set<string> &dict) {
int size = s.size();
vector<bool> breaks(size, false);
for (int i = size - 1; i >= 0; --i) {
for (int j = i; j < size; ++j) {
if (dict.find(s.substr(i, j-i+1)) != dict.end()) {
if (j + 1 >= size || breaks[j+1]) {
breaks[i] = true;
break;
}
}
}
}
return breaks[0];
}
};
一年之后,还是想半天。。。