class Solution {
public:
vector<string> res;
void dfs(int start,string& curString,const string& s,const vector<vector<bool> >& dp,const unordered_set<string> &dict)
{
if(start==s.size())
{
res.push_back(curString);
return;
}
for(int i=start+1;i<=s.size();++i)
{
if(dict.count(s.substr(start,i-start)))
{
string tmp=s.substr(start,i-start);
if(i==s.size())
{
curString=curString+(curString.size()==0?tmp:" "+tmp);
dfs(i,curString,s,dp,dict);
string::size_type pos=curString.rfind(' ');
if(pos==string::npos)
{
curString="";
}
else
{
curString=curString.substr(0,pos);
}
}
else
{
if(dp[i][s.size()])
{
curString=curString+(curString.size()==0?tmp:" "+tmp);
dfs(i,curString,s,dp,dict);
string::size_type pos=curString.rfind(' ');
if(pos==string::npos)
{
curString="";
}
else
{
curString=curString.substr(0,pos);
}
}
}
}
}
}
vector<string> wordBreak(string s, unordered_set<string> &dict) {
int n=s.size();
if(n<2)
{
vector<string> res;
if(dict.count(s))
{
res.push_back(s);
}
return res;
}
vector<vector<bool> > dp(n+1,vector<bool>(n+1,false));
for(int i=n-1;i>=0;--i)
{
for(int j=i+1;j<=n;++j)
{
if(dict.count(s.substr(i,j-i)))
{
dp[i][j]=true;
continue;
}
for(int k=i+1;k<j;++k)
{
if(dp[i][k]&&dp[k][j])
{
dp[i][j]=true;
break;
}
}
}
}
string str;
dfs(0,str,s,dp,dict);
return res;
}
};
基本思路,先做出dp数组,这样在回溯时可以及时停止回溯,避免不必要的回溯。注意这里传入参数curString用了引用,所以在每次递归后要记得还原。这样做的本意是希望避免参数复制加快运行速度,但是效果不好,反而不如直接传值,因为在复原时要通过rfind参数找到还原位置,消耗了不必要的时间。