您的位置:首页 > 其它

leetcode:string hard系列三:word break

2016-10-18 22:30 435 查看
https://leetcode.com/problems/word-break/

https://leetcode.com/problems/word-break-ii/

class Solution {
public:
vector<string> wordBreak(string s, unordered_set<string>& wordDict) {
vector<string>res;
string tmp;
__wordBreak(s, 0, wordDict, tmp, res);
for (int i=0;i<res.size();i++)
{
res[i].erase(res[i].begin());
}
return res;
}
void __wordBreak(string s, int begin, unordered_set<string>& wordDict,string tmp, vector<string>&res)
{
if (begin >= s.size())return;
string substring = s.substr(begin);
string tmp_Cur(tmp);
if (wordDict.find(substring) != wordDict.end())
{
tmp_Cur += " " + substring;
res.push_back(tmp_Cur);
}
if (begin == s.size() - 1)return;//只剩下一个字符串
//接下来,分割
for (int i=begin+1;i<s.size();i++)
{
tmp_Cur = tmp;
string ssub = s.substr(begin, i - begin);
if (wordDict.find(ssub) != wordDict.end())
{
tmp_Cur += " " + ssub;
__wordBreak(s, i, wordDict, tmp_Cur, res);
}
}
}
};采用递归算法,超时,把这个字符串暴力搜索出所有的拼接情况,然后,求出最短

DP算法:

class Solution {
public:
bool wordBreak(string s, unordered_set<string>& wordDict) {
int n = s.size();
vector<bool>dp(n + 1, false);
dp[0] = true;
for (int i=1;i<=n;i++)
{
for (int j=i-1;j>=0;--j)
{
if(dp[j]) //从[0,j)到[j,i)的判断
{
if (wordDict.find(s.substr(j, i - j)) != wordDict.end())
{
dp[i] = true;
break;
}
}

}
}
return dp
;
}
};动态规划,判断当前位的时候,分解成:从[0,j)到[j,i)的判断,前提是[0,j)已经满足了拼接条件

转为BFS
bool wordBreak(string s, unordered_set<string> &dict) {
// BFS
queue<int> BFS;
unordered_set<int> visited;

BFS.push(0);
while(BFS.size() > 0)
{
int start = BFS.front();
BFS.pop();
if(visited.find(start) == visited.end())
{
visited.insert(start);
for(int j=start; j<s.size(); j++)
{
string word(s, start, j-start+1);
if(dict.find(word) != dict.end())
{
BFS.push(j+1); //BFS里面存储的意义:j->j之前的都能够break成功,因为j之前的break方式可能有很多种,所以用visted只保留其中一种
if(j+1 == s.size())
return true;
}
}
}
}

return false;
}

 word break II就是word break里面所有的break可能列举出来

class Solution {
private:
unordered_map<string, vector<string>> m; //通过map,减少迭代次数

vector<string> combine(string word, vector<string> prev){
for(int i=0;i<prev.size();++i){
prev[i]+=" "+word; //这里的prev[i]已经是rem里面的string break的结果集
}
return prev;
}

public:
vector<string> wordBreak(string s, unordered_set<string>& dict) {
if(m.count(s)) return m[s]; //take from memory
vector<string> result;
if(dict.count(s)){ //a whole string is a word
result.push_back(s);
}
for(int i=1;i<s.size();++i){ //就算s整个都在dict里面,但是也要尝试着继续分解
string word=s.substr(i);
if(dict.count(word)){ //只有当存在的时候,才会继续调用递归
string rem=s.substr(0,i);
vector<string> prev=combine(word,wordBreak(rem,dict));
result.insert(result.end(),prev.begin(), prev.end());
}
}
m[s]=result; //memorize
return result;
}
};


Stefan大神的精简版代码:
vector<string> wordBreak(string s, unordered_set<string>& wordDict) {
unordered_map<int, vector<string>> memo {{s.size(), {""}}};
function<vector<string>(int)> sentences = [&](int i) {
if (!memo.count(i))  //memo[i]表示的是s.substr(i)的break结果,用map的好处就是递归收敛
for (int j=i+1; j<=s.size(); j++)
if (wordDict.count(s.substr(i, j-i)))
for (string tail : sentences(j)) //这个地方递归
memo[i].push_back(s.substr(i, j-i) + (tail=="" ? "" : ' ' + tail));//因为每个memo[i]都初始化为"",如果tail为空,直接忽略,
return memo[i];};<span style="white-space:pre">						</span>                  //否则:+空格+tail
return sentences(0);  //得到就是s.substr(0)的所有break可能
}


function是一个封装函数的容器,定义了一个 输入为int,输出为 vector<string>的function,并生成 sentences这个对象,后面lambda函数对sentences copy assignment
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息