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"]
.
题意:有字符串s和字典dict,将s分割成由字典中出现的若干单词,用空格分开,求所有分割方法。
分析:首先,建立从s从头到尾的可行路径,即dp[i]为从i出发下一个可行位置列表。
为了建立dp[i],要从尾向头找单词,即从n-1到0枚举单词结尾位置j,每个位置找所有可行单词的起始位置i,dp[i].push_back(j)
这样反向建立路径,正向遍历时就一定是可行路径了
注意:若正向建立,那么会有很多路径不能到达终点,导致搜索空间变大,我就是因为这个问题TLE很多次
然后,用dfs或bfs从头搜索,记录结果即可。
代码:
class Solution {
public:
vector<string> wordBreak(string s, unordered_set<string> &dict) {
vector<string> ans;
if(dict.empty()) return ans;
if(s.empty())
{
ans.push_back(s);
return ans;
}
int len = s.length();
vector<int> tmp;
vector<vector<int> > dp(len,tmp);
for(int i=len-1; i>=0; i--)
{
if(i<len-1 && dp[i+1].size()==0)
continue;
for(int j=i; j>=0; j--)
{
string cur = s.substr(j,i-j+1);
if(dict.find(cur)!=dict.end())
dp[j].push_back(i);
}
}
stack<int> st;
stack<string> sts;
st.push(0);
sts.push("");
while(!st.empty())
{
int ind = st.top();
string pre = sts.top();
st.pop(),sts.pop();
for(int i=0; i<dp[ind].size(); i++)
{
int j = dp[ind][i];
string now = s.substr(ind,j-ind+1);
string add = pre;
if(add.length()>0) add += ' ';
add += now;
if(j+1>=len)
{
ans.push_back(add);
}
else
{
st.push(j+1);
sts.push(add);
}
}
}
return ans;
}
};