题目描述
给定一个字符串s和一组单词dict,在s中添加空格将s变成一个句子,使得句子中的每一个单词都是dict中的单词
返回所有可能的结果
例如:给定的字符串s =“catsanddog”,
dict =[“cat”, “cats”, “and”, “sand”, “dog”].
返回的结果为[“cats and dog”, “cat sand dog”].
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”].
每次做动态规划的题目总是能让我产生我可能不适合写代码的想法,这道题目更是虐哭我…
动态规划算法,我的理解,就是通过记录一些信息,避免对某些情况的重复计算,从而减少递归次数。
原理很简单,可真正写起来各种问题都出来了…最终通过不断的调试终于通过了…不容易…
思路:
- 和word-break的第一题一样,这道题也是对字符串s进行拆分,不过这一题要求把拆分后的每个单词间加上空格输出出来。既然要加空格,首先得知道s拆成了哪些单词,所以我用了一个vector(tem)来存拆分后的单词,用另一个vector(res)来存拆分成功的字符串;
- 一旦拆分成功了就把tem中的单词用空格串起来,push到res里。总体思路和word-break很像,代码似乎不复杂,但调试过程真心累,直接看代码吧。
这里还要吐槽一下牛客网的评分标准,顺序不一样就直接给错了,太不智能了!!
本来就难还这么严格,于是愤怒投奔leetcode,终于通过了~~
代码:
class Solution {
public:
vector<string> wordBreak(string s, vector<string>& wordDict) {
if (s.length() == 0)
return res;
bool *dp = new bool[s.length() + 1];
memset(dp, 0, s.length() + 1);
unordered_set<string> dict;
for (int i=0; i<wordDict.size(); i++)
dict.insert(wordDict[i]);
BreakWord(s, dict, dp);
return res;
}
void BreakWord(string s, unordered_set<string> &dict, bool *cannot)
{
int len = s.length();
if (len == 0 && !tem.empty()) // 当拆分成功时,把单词间加上空格后的字符串push到res里
{
string str;
for (int i = 0; i < tem.size() - 1; i++)
{
str += tem[i];
str += " ";
}
str += tem[tem.size() - 1];
res.push_back(str);
}
if (cannot[len]) // 如果已知不能拆分,直接return
return;
int ressize = res.size(); // 记录是否成功拆分
for (int i = 1; i <= len; i++)
{
string tmp = s.substr(0, i);
if (dict.find(tmp) != dict.end())
{
tem.push_back(tmp);
BreakWord(s.substr(i, len - i), dict, cannot);
tem.pop_back(); // 不论有没有拆分成功,都要pop掉tmp
}
}
if (res.size() == ressize) // 如果为true,则表示没能成功拆分,做好记录防止重复计算
cannot[len] = true;
}
private:
vector<string> res;
vector<string> tem;
};
大佬们的代码:
vector<string> wordBreak(string s, unordered_set<string> &dict) {
vector<string> res;
if(dict.find(s) != dict.end()) res.push_back(s);
int len = s.size();
for(int i=1; i< len; ++i){
string word = s.substr(i);
if(dict.find(word) == dict.end()) continue;
vector<string> tempRes = wordBreak(s.substr(0, i), dict);
Combine(tempRes, word);
res.insert(res.begin(), tempRes.begin(), tempRes.end());
}
return res;
}
void Combine(vector<string>& v, const string& str){
for(auto& e : v) { e +=" " + str;}
}
瞅瞅这是人能写出来的吗?才这几行?
今天零食吃完了,明天再看zz