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"]
.
這道題是word break1的升級版,要求生成所有可能的結果。
一般而言,碰到這種要求生成所有結果的題目,最直接的想法就是DFS。這道題當然也可以直接用DFS做了。我們可以依次遍歷每個prefix,如果當前的prefix在dict中,那麼就遞歸往下遍歷,用temp保存當前能夠被break的部分,一切結束之後在backtrack。這個思路已經很熟悉了,就不多寫了。
但是,這樣直接的DFS是很慢很慢的,因爲會有大量的東西被重複計算了。所有,很自然的想到要用DP。前面word break I中,DP中的table或者cache用來記錄當前位置的substring可不可以被break。在這道題中,DP應該用來記錄當前位置被break之後的結果,也就是一個ArrayList。
下面的程序是用cache+recursive的方式寫的,除了cache保存的東西由boolean值換成了ArrayList,其它的幾乎和word break I中完全一樣。另外還有一點值得注意,就是在cache中要加入空字符串的base case,因爲在遞歸中,我用ArrayList的大小作爲了給定位置的substring是否能被break的判斷標準。
這週末寫出table+iterative的版本來。
public class Solution {
public void wordBreakHelper(String s, Set<String> dict, HashMap<String, List<String>> cache) {
if(s.length()==0) return;
cache.put(s, new ArrayList<String>());
for(int i=1; i<=s.length(); i++) {
String firstHalf=s.substring(0, i), secondHalf=s.substring(i, s.length());
if(dict.contains(firstHalf)) {
if(!cache.containsKey(secondHalf)) {
wordBreakHelper(secondHalf, dict, cache);
}
if(cache.get(secondHalf).size() > 0) {
for(String ss : cache.get(secondHalf)) {
StringBuilder builder = new StringBuilder(firstHalf).append(" ").append(ss);
if(ss.length()==0) builder.deleteCharAt(builder.length()-1);
cache.get(s).add(builder.toString());
}
}
}
}
return;
}
public List<String> wordBreak(String s, Set<String> dict) {
if(s==null) return new ArrayList<String>();
HashMap<String, List<String>> cache = new HashMap<String, List<String>>();
ArrayList<String> baseCase = new ArrayList<String>();
baseCase.add("");
cache.put("", baseCase);
wordBreakHelper(s, dict, cache);
return cache.get(s);
}
}