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"].
思路:
我们从第一个字母开始,遍历字典,看从第一个字母开始能组成哪个在字典里的单词,如果找到了一个,就在这个单词的结束位置的下一个字母处,建立一个列表,记录这个词(保存到一个列表的数组)。当遍历完成这个词典并找出所有以第一个字母开头的词以后,我们进入下一轮搜索。下一轮搜索只在之前找到的词后面位置开始,如果这个位置不是一个词的下一个字母位置,我们跳过,这样我们相当于构建了一个树(实际上是列表数组)。每个找到的词都是这个树的一个分支,有了这个“”树“”,然后我们在用深度优先搜索,把路径加到当中就行。
[cpp] view plain copy
class Solution
{
public:
void countBreak(string& s, int index, string str,
vector<int>& dp, unorderd_set<string>& dict,
vector<string>& res, int &length)
{
string substr;
for (int len=1; index+len<=length; ++len)
{
if (dp[index+len] && dict.find(s.substr(index, len))!=dict.end())
{
substr = s.substr(index,len);
if (index+len>=length)
{
res.push_back(str+substr);
}
else
{
countBreak(s, index+len, str+substr+" ", dp, dict, res, length);
}
}
}
}
vector<string> wordBreak(string s, unordered_set<string>& dict)
{
int len = s.size();
vector<string> res;
if (len<1)
{
return res;
}
vector<int> dp(len+1, 0);
dp[0] = 1;
for (int i=1; i<=len; i++)
{
for (int j=i-1; j>=0; --j)
{
if (dp[j] && dict.find(s.substr(j, i-j)!=dict.end())
{
dp[i] = 1;
}
}
}
if (dp[len]==0)
{
return res;
}
countBreak(s, 0, "", dp, dict, res, len);
return res;
}
};
注意:在backtracking 的时候不用考虑下标超姐的情况,直接将所有到0的都加入结果就行了,因为我们在建这个路径时,就是从0开始建的,不可能越界。