- 单词拆分 II
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
说明:
分隔时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:
输入:
s = “catsanddog”
wordDict = [“cat”, “cats”, “and”, “sand”, “dog”]
输出:
[
“cats and dog”,
“cat sand dog”
]
示例 2:
输入:
s = “pineapplepenapple”
wordDict = [“apple”, “pen”, “applepen”, “pine”, “pineapple”]
输出:
[
“pine apple pen apple”,
“pineapple pen apple”,
“pine applepen apple”
]
解释: 注意你可以重复使用字典中的单词。
示例 3:
输入:
s = “catsandog”
wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
输出:
[]
题目使用递归回溯求解,但是求解之前首先判断下是否存在可能的句子,不然时间复杂度太大。。。
C++实现
执行用时 :4 ms, 在所有 C++ 提交中击败了99.67%的用户
内存消耗 :10.5 MB, 在所有 C++ 提交中击败了85.25%的用户
代码如下
class Solution {
public:
vector<string> vec;
vector<string> temp;
vector<string> wordBreak(string s, vector<string>& wordDict) {
set<string> word(wordDict.begin(),wordDict.end());
if(!wordBreak2(s,wordDict,word))
return vec;
getword(s,0,word);
return vec;
}
void getword(string &s,int lo,set<string> &word)
{
if(lo==s.size())
{
string str_temp;
str_temp+=temp[0];
for(int i=1;i<temp.size();i++)
{
str_temp+=" ";
str_temp+=temp[i];
}
vec.push_back(str_temp);
return;
}
for(int j=lo;j<s.size();j++)
{
if(word.count(s.substr(lo,j-lo+1))!=0)
{
temp.push_back(s.substr(lo,j-lo+1));
getword(s,j+1,word);
temp.pop_back();
}
}
}
bool wordBreak2(string &s,vector<string>& wordDict,set<string> &word)
{
if(s.size()==0)
return true;
if(wordDict.size()==0)
return false;
vector<bool> dp(s.size()+1,false);
dp[0]=true;
int minlen=INT_MAX;
int maxlen=0;
for(int k=0;k<wordDict.size();k++)
{
if(minlen>wordDict[k].size())
minlen=wordDict[k].size();
if(maxlen<wordDict[k].size())
maxlen=wordDict[k].size();
}
for(int i=minlen-1;i<s.size();i++)
{
for(int j=max(0,i-maxlen+1);j<=i;j++)
{
if(dp[j]&&word.count(s.substr(j,i-j+1))!=0)
{
dp[i+1]=true;
break;
}
}
}
return dp[s.size()];
}
};