LeetCode之“动态规划”:Word Break && Word Break II

时间:2021-05-17 16:21:33

  1. Word Break

  题目链接

  题目要求:

  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".

  博文Word Break -- LeetCode提及了动态规划的思想:

  首先我们要决定要存储什么历史信息以及用什么数据结构来存储信息。然后是最重要的递推式,就是如从存储的历史信息中得到当前步的结果。最后我们需要考虑的就是起始条件的值。

  下边是该博文对该题目的分析:

  首先我们要存储的历史信息res[i]是表示到字符串s的第i个元素为止能不能用字典中的词来表示,我们需要一个长度为n的布尔数组来存储信息。然后假设我们现在拥有res[0,...,i-1]的结果,我们来获得res[i]的表达式。思路是对于每个以i为结尾的子串,看看他是不是在字典里面以及他之前的元素对应的res[j]是不是true,如果都成立,那么res[i]为true,写成式子是

  LeetCode之“动态规划”:Word Break && Word Break II

  具体程序如下:

 class Solution {
public:
bool wordBreak(string s, unordered_set<string>& wordDict) {
int szS = s.size();
if(szS == )
return false; vector<bool> dp(szS + , false);
dp[] = true;
for(int i = ; i < szS + ; i++)
{
for(int j = i - ; j > -; j--)
{
if(dp[j] && wordDict.find(s.substr(j, i - j)) != wordDict.end())
{
dp[i] = true;
break;
}
}
} return dp[szS];
}
};

  2. Word Break II

  题目链接

  题目要求:

  Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.

  Return all such possible sentences.

  For example, given
  s = "catsanddog",
  dict = ["cat", "cats", "and", "sand", "dog"].

  A solution is ["cats and dog", "cat sand dog"].

  其实这道题比上一道题理解来得容易,直接用Brute Force或者想直接利用上一题的结果来得到最终结果,都会超时。具体的,就是对输入进行检查,看看输入是否可以分解的,这样就可以跟超时了。

  Brute Force程序:

 class Solution {
public:
bool isValid(string s, unordered_set<string>& wordDict)
{
return wordDict.find(s) != wordDict.end();
} void dfs(string s, string tmp, vector<string>& res, unordered_set<string>& wordDict)
{
if (s.size() == )
{
tmp.pop_back(); // delete blank space
res.push_back(tmp);
return;
} int sz = s.size();
for(int i = ; i < sz + ; i++)
{
string str = s.substr(, i);
if(isValid(str, wordDict))
dfs(s.substr(i), tmp + str + " ", res, wordDict);
}
} vector<string> wordBreak(string s, unordered_set<string>& wordDict) {
vector<string> res;
int szS = s.size();
if(szS == )
return res; vector<bool> dp(szS + , false);
dp[] = true;
for(int i = ; i < szS + ; i++)
{
for(int j = i - ; j > -; j--)
{
if(dp[j] && wordDict.find(s.substr(j, i - j)) != wordDict.end())
{
dp[i] = true;
break;
}
}
} if(dp[szS])
dfs(s, "", res, wordDict); return res;
}
};

  利用上一题的结果:

 class Solution {
public:
bool isValid(string s, unordered_set<string>& wordDict)
{
return wordDict.find(s) != wordDict.end();
} void dfs(string s, string tmp, vector<string>& res, vector<int> inDictPos, unordered_set<string>& wordDict)
{
if (s.size() == )
{
tmp.pop_back(); // delete blank space
res.push_back(tmp);
return;
}
int sz = inDictPos.size();
if (sz > )
{
for (int i = ; i < sz; i++)
{
int diff = inDictPos[i] - inDictPos[];
if (diff <= s.size())
{
string subStr = s.substr(, diff);
if (isValid(subStr, wordDict))
{
vector<int> _inDictPos(inDictPos);
_inDictPos.erase(_inDictPos.begin(), _inDictPos.begin() + i);
string tmpStr = s.substr(diff);
dfs(s.substr(diff), tmp + subStr + " ", res, _inDictPos, wordDict);
}
}
}
}
} vector<string> wordBreak(string s, unordered_set<string>& wordDict) {
// Implemented in Word Break I
int szS = s.size();
vector<bool> dp(szS + , false);
vector<int> inDictPos;
dp[] = true;
inDictPos.push_back();
for(int i = ; i < szS + ; i++)
{
for(int j = i - ; j > -; j--)
{
if(dp[j] && wordDict.find(s.substr(j, i - j)) != wordDict.end())
{
dp[i] = true;
inDictPos.push_back(i);
break;
}
}
} vector<string> res;
if(dp[szS])
dfs(s, "", res, inDictPos, wordDict); return res;
}
};

  相比较之下,当然只用BF就够了,而且还来得简单。