单词拆分 II
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
说明:
分隔时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:
输入:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
输出:
[
"cats and dog",
"cat sand dog"
]
上一篇单词拆分的时候就做了一个扩展思考即输出拆分后的单词组合。和这个题可以相互转化。
通过动态规划判断出字符串s是否可以被拆分,如果可以则通过dfs找出对应的组合。
dfs是反向查的,同样是利用了之前动态规划的特性
//搜索
void dfsWordBreak(std::string s, std::vector<int>& dp, vector<string>& wordDict, size_t _end, std::string str, std::vector<std::string>& rs)
{
if (_end == 0)
{
//通过了
rs.push_back(str);
return;
}
for (int i = _end-1; i >=0; --i)
{
if (dp[i])
{
//这个str看能不能做做优化
std::string _str = s.substr(i, _end - i);
if(find(wordDict.begin(), wordDict.end(), _str)!=wordDict.end())
{
if(!str.empty())
_str = _str + " " + str;
//cout<<_str <<endl;
dfsWordBreak(s, dp, wordDict, i, _str, rs);
}
}
}
}
vector<string> wordBreak(string s, vector<string>& wordDict) {
std::vector<std::string> rs;
if (s.empty() || wordDict.size() <= 0)
return rs;
std::vector<int> dp(s.size()+1);
size_t len = s.size();
dp[0] = 1;
for (int i = 1; i <= len; ++i)
{
for (size_t j = 0; j < i && !dp[i]; ++j)
{
std::string check = s.substr(j, i-j);
dp[i] = (dp[j]>0 && (find(wordDict.begin(), wordDict.end(), check)!=wordDict.end()))?1:0;
}
}
std::cout<<std::endl;
if(dp[len])
{
dfsWordBreak(s, dp, wordDict, len, "", rs);
}
return rs;
}