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