您的位置:首页 > 编程语言 > C语言/C++

LeetCode 140 Word Break II--In C++

2016-06-21 09:46 671 查看
思路:

首先想到的是递归的解法,但是考虑到TLE的问题,此路不通。其次是动态规划的版本,结合139 Word Break ,只需扩展那个动态数组就可以了。139中用一个bool数组表示dp[i]之前的串能否形成切分。那么在这个问题中,可以将最后一个成功切出来的单词挂在i角标的下面。

这时,最好用一个vector<string>的数组来存储最后一个切下的单词。


这样先用动态规划扫一遍之后,会得到上图的结构。

然后用dfs从后向前路径搜索,找到e下的“code”通过他的长度就能找到下一个位置t,以此类推,直到游标越出边界递归到达终点。

谈谈走的弯路:

因为引用了139中的代码,所以一开始误以为dp[i]==true且新切下来的串在字典中就可以挂在i位置,但这样的话有很多多余的路径,导致TLE。直到最后那个很长的case才发现了这一点,究其原因还是思路上模糊了。用了一个多小时才定位到这个问题。。。郁闷。

vector<string> result;
void dfsLoadResult(int i, vector<string>* carry, vector<string> pro){//填充结果
//i表示以i角标为结束范围,pro记录着过程中的单词
if (i<0){
return;
}
if (i == 0){//一个有效解,向result装填
int prolen = pro.size();
if (prolen == 0){
return;
}
string ts = "";
ts = ts + pro[prolen - 1];
for (int i = prolen - 2; i >= 0; i--){
ts = ts + " " + pro[i];
}
result.push_back(ts);
return;
}

int carrylen = carry[i].size();//查看i下挂了几个单词
if (carrylen == 0){
return;
}
for (int k = 0; k < carrylen; k++){
int ti = carry[i][k].size();//i下第k个单词的长度
vector<string> tepro = vector<string>(pro);
tepro.push_back(carry[i][k]);
dfsLoadResult(i - ti, carry, tepro);
}

}
//*************************辅助**************************//
vector<string> wordBreak(string s, unordered_set<string>& wordDict) {
result.clear();

int slen = s.size();
if (slen == 0){
return result;
}
else if (wordDict.size() == 0){
return result;
}
int maxslong = -1;//得到字典里最长的单词的长度
for (unordered_set<string>::iterator it = wordDict.begin(); it != wordDict.end(); it++){
int slong = (*it).size();
if (maxslong<slong){
maxslong = slong;
}
}

bool * dp = new bool[slen + 1];
dp[0] = true;//相当于s[-1]的位置指定为true作为哨兵

vector<string>* carry = new vector<string>[slen + 1];//用来保存以第i个字符作为结尾的所有单词

for (int i = 1; i <= slen; i++){
for (int len = maxslong; len >= 1; len--){
if (i - len<0){
continue;
}
string cutstr = s.substr(i - len, len);
dp[i] = (dp[i - len] && (wordDict.find(cutstr) != wordDict.end())) || dp[i];
//不光dp[i-len]要为true,他下面必须要有挂的单词才能给carry[i]继续挂单词
if ((carry[i-len].size()>0||i-len==0) && (wordDict.find(cutstr) != wordDict.end())){
carry[i].push_back(cutstr);//将这个单词挂在carry[i]下
}
}
}
if (dp[slen] == false){//无解的情况
return result;
}
vector<string> tt;
dfsLoadResult(slen, carry, tt);

delete[] dp;
delete[] carry;

return result;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息