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"].
分析:最基本的思路就是逐个尝试咯,从第一个字符开始检查能否在字典中找到子串,如果可以找到,加入解,在从其后的位置开始找,直到最后,刚刚好结束,就找到一个解。
因为可能从某个位置开始能找到两个不同长度的单词,所以要回溯寻找不同的解。
处理技巧:
1,先判断整个字符串能不能刚好被分割,因为有重复子问题,考虑用动态规划。
2,用递归来处理回溯,加上一个单词,递归往后求解,之后再减去这个单词,以保证可以遍历以此点开始的所有单词。
public class Solution {
public List<String> wordBreak(String s, Set<String> dict) {
List<String> res = new ArrayList<String>();
if(s==null || s.length()==0) return res;
//首先判断s能不能刚好被分割
//这里用动态规划的方法,table[i]记录[0,i)这个子问题的解
//[0,i)可以分割为true,否则为false
boolean[] table = new boolean[s.length()+1];
table[0] = true;
for(int i=1; i<=s.length(); i++){
for(int k=0; k<i; k++){
//[0,k)可以分割,同时[k,i)在字典里,说明[0,i)可以分割
//记录中间结果避免重复求解子问题
table[i] = table[k] && dict.contains(s.substring(k,i));
if(table[i] == true)
break;
}
}
//如果s不能被分割,就没有必要继续求解下去
if(!table[s.length()]) return res;
StringBuilder sb = new StringBuilder();
dfs(s, 0, sb, res, dict);
return res;
}
private void dfs(String s, int start, StringBuilder sb, List<String> res, Set<String> dict){
//递归终结
if(start >= s.length()){
//注意要新建一个字符串
res.add(new String(sb));
return;
}
for(int i=start+1; i<=s.length(); i++){
String sub = s.substring(start, i);
if(dict.contains(sub)){
int currLen = sb.length();
if(currLen != 0){
sb.append(" ");
}
sb.append(sub);
dfs(s, i, sb, res, dict);
sb.delete(currLen, sb.length());
}
}
}
}