Two dynamic programming problem
problem II can use the code of problem I
Word Break I
class Solution {
public:
int longestWord(unordered_set<string> dict) {
unordered_set<string>::iterator it;
int ret = 0;
for (it = dict.begin(); it != dict.end(); it++) {
if ((*it).length() > ret)
ret = (*it).length();
}
return ret;
}
bool wordBreakFunc(string s, unordered_set<string> &dict, int len) {
int i, j, str_len;
bool* ret;
unordered_set<string>::iterator it;
str_len = s.length();
ret = new bool[str_len + 1];
ret[str_len] = true;
for (i = 0; i < str_len; i++)
ret[i] = false;
len = len < str_len ? len : str_len;
for (i = str_len - 1; i >= 0; i--) {
for (j = 0; j < len; j++) {
if (i + j >= str_len)
break;
it = dict.find(s.substr(i, j+1));
if (it != dict.end()) {
if (ret[i+j+1]) {
ret[i] = true;
break;
}
}
}
}
return ret[0];
}
bool wordBreak(string s, unordered_set<string> &dict) {
int max_len;
bool res;
max_len = longestWord(dict);
res = wordBreakFunc(s, dict, max_len);
return res;
}
};
The main idea behind this problem is calculating from right to left. if sub_string from i t o j can be found in dictionary and from i+j to the end is breakable, then from i to end is breakable. There is a list to record breakable or not from each index to the end.
Word Break II
class Solution {
public:
bool *can_bk;
int len;
int longestWord(unordered_set<string> dict) {
unordered_set<string>::iterator it;
int ret = 0;
for (it = dict.begin(); it != dict.end(); it++) {
if ((*it).length() > ret)
ret = (*it).length();
}
return ret;
}
void wordBreakFunc(string s, unordered_set<string> &dict) {
int i, j, str_len;
unordered_set<string>::iterator it;
str_len = s.length();
for (i = str_len - 1; i >= 0; i--) {
for (j = 0; j < len; j++) {
if (i + j >= str_len)
break;
it = dict.find(s.substr(i, j+1));
if (it != dict.end()) {
if (can_bk[i+j+1]) {
can_bk[i] = true;
break;
}
}
}
}
}
void recordSentence(string s, unordered_set<string> &dict, vector<string> &res, string &tmp, int st) {
int i;
unordered_set<string>::iterator it;
if (st == s.length()) {
res.push_back(tmp.substr(0, tmp.length() - 1));
}
else {
for (i = 0; i < len; i++) {
if (st+i+1 > s.length())
break;
if (can_bk[st+i+1]) {
it = dict.find(s.substr(st, i+1));
if (it != dict.end()) {
tmp += (*it + " ");
recordSentence(s,dict,res,tmp,st+i+1);
tmp = tmp.substr(0, tmp.length() - (*it).length() - 1);
}
}
}
}
}
vector<string> wordBreak(string s, unordered_set<string> &dict) {
int max_len, str_len, i;
vector<string> res;
string tmp;
if (s == "")
return res;
str_len = s.length();
max_len = longestWord(dict);
len = str_len < max_len ? str_len : max_len;
can_bk = new bool[str_len + 1];
can_bk[str_len] = true;
for (i = 0; i < str_len; i++)
can_bk[i] = false;
wordBreakFunc(s, dict);
recordSentence(s,dict, res, tmp, 0);
return res;
}
};
The basic idea is almost same as Word Break I. Using the same methodology to record from each index to the end is breakable or not. Then using DFS ALG to record sentence by adding every findable words if and only if the right substring is breakable. Be careful about the space, when you push the string to the return vector, remember to remove the last space. This space is inserted in order to keep generality for previous operation.