问题描述:
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”].
分析:这道题与上题几乎一样,但是这里要求返还所有的满足条件的solution,所以,很容易想到使用DFS,果不其然会TLE,然后换成DP算法,同样TLE,都是在同一个case出错,看了网友的介绍,只要在继续之前先判断是否可以word break即可。因为判断是否可以wordbreak的时间复杂度为O(n2),而真正切割的时间复杂度为O(n3)。但是好像更像专门为那个超长的case准备的,,
哦,对了,在递归的过程中,最好遍历wordDict而不是遍历整个string。可以节省一定时间。
递归版本:TLE
private void solve(List<String> res,String s,String cur,Set<String> wordDict){
if(s.length()<=0) {
res.add(cur);
return;
}
for(String str:wordDict){
int len = str.length();
if(len<=s.length() && s.substring(0,len).equals(str)){
solve(res,s.substring(len),cur.length()==0?str:cur+" "+str,wordDict);
}
}
}
public List<String> wordBreak(String s, Set<String> wordDict) {
List<String> res = new LinkedList<>();
solve(res,s,"",wordDict);
return res;
}
DP版本:TLE
public List<String> wordBreak(String s,Set<String> wordDict){
List<List<String>> dpArray = new ArrayList<>();
for(int i = 1;i<=s.length();i++){
dpArray.add(new LinkedList<>());
for(int j = 0;j<i;j++){
String substr = s.substring(j,i);
if(wordDict.contains(substr)){
if(j==0){
dpArray.get(i-1).add(substr);
}else if(dpArray.get(j-1).size()>0){
List<String> prevList = dpArray.get(j-1);
int size = prevList.size();
List<String> tmp = dpArray.get(i-1);
for(int k = 0;k<size;k++){
tmp.add(prevList.get(k)+" "+substr);
}
}
}
}
}
return dpArray.get(s.length()-1);
}
AC版本:
public class Solution {
private void solve(List<String> res,String s,String cur,Set<String> wordDict){
if(s.length()<=0) {
res.add(cur);
return;
}
for(String str:wordDict){
int len = str.length();
if(len<=s.length() && s.substring(0,len).equals(str)){
solve(res,s.substring(len),cur.length()==0?str:cur+" "+str,wordDict);
}
}
}
public List<String> wordBreak(String s, Set<String> wordDict) {
List<String> res = new LinkedList<>();
if(!isWordBreak(s,wordDict))
return res;
solve(res,s,"",wordDict);
return res;
}
private boolean isWordBreak(String s,Set<String> wordDict){
int length = s.length();
boolean[] words = new boolean[length];
for(int i = 1;i<=length;i++){
int j;
for(j = 0;j<i;j++){
String substr = s.substring(j,i);
if(wordDict.contains(substr) && (j==0 || words[j-1])) {
words[i-1] = true;
break;
}
}
if(j == i)
words[i-1] = false;
}
return words[length-1];
}
}