题目描述
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:深度优先。
- 建立ArrayList<String>类型的数组scanned
- 找出dict中匹配s的前缀,加入到scanned[0]中,并且建立scanned[word.length()。
import java.util.ArrayList;
import java.util.Set;
import java.util.List;
public class Solution {
private ArrayList<String>[] scanned;
private ArrayList<String> results = new ArrayList<String>();
public ArrayList<String> wordBreak(String s, List<String> dict) {
scanned = new ArrayList[s.length()];
scanned[0] = new ArrayList<>();
boolean reachable = false;
for (int i = 0; i < s.length(); i++){
if(scanned[i] == null)
continue;
for(String word:dict){
if(i + word.length() <= s.length() && word.equals(s.substring(i,i+word.length()))){
scanned[i].add(word);
if(i + word.length() == s.length())
reachable = true;
else if((scanned[i+word.length()] == null) && (i + word.length() < s.length()))
scanned[i + word.length()] = new ArrayList<>();
}
}
}
if(!reachable)
return results;
dfs(s, 0, new ArrayList<>(), dict);
return results;
}
public void dfs(String s, int from, List<String> words, List<String> dict){
if(from == s.length())
{
String result = "";
for(int i = 0; i < words.size(); i++)
{
if(i > 0)
result += " ";
result += words.get(i);
}
results.add(result);
return;
}
for (String word:scanned[from])
{
words.add(word);
dfs(s, from + word.length(), words, dict);
words.remove(words.size() - 1);
}
}
}
上面代码在niukewang上不能通过,因为没有按照dict中前缀出现的次序输出,但是题目给的样例也没有按照顺序输出。>_<。最后,在leetcode上面AC。
方法二:字典树+深度优先搜索
- 首先对dict中的单词建立字典树
- 然后判断s是否可以由dict中的单词来组成
- 使用dfs对s进行相应的分割。
- 用得到的分割数组生成分割结果
import java.util.List;
import java.util.Set;
import java.util.ArrayList;
public class Solution {
private TriNode root;
//字典树数据结构
class TriNode {
boolean isWord;
TriNode[] nexts = new TriNode[26];
TriNode add(char ch){
int i = ch - 'a';
if (nexts[i] != null)
return nexts[i];
nexts[i] = new TriNode();
return nexts[i];
}
}
public ArrayList<String> wordBreak(String s, Set<String> dict) {
ArrayList<String> results = new ArrayList<>();
if(s == null || dict == null)
return results;
root = new TriNode();
//dict建立字典树
for (String word:dict){
char[] wa = word.toCharArray();
TriNode current = root;
for (int i = 0; i < wa.length; i++)
current = current.add(wa[i]);
current.isWord = true;
}
char[] sa = s.toCharArray();
boolean[] reachable = new boolean[sa.length+1];
reachable[0] = true;
for (int i = 0; i < sa.length; i++){
if(!reachable[i])
continue;
TriNode current = root;
for (int j = i; j < sa.length && current!=null; j++){
current = current.nexts[sa[j]-'a'];
if (current != null && current.isWord)
reachable[j+1] = true;
}
}
if(!reachable[sa.length])
return results;
find(sa, 0, new int[sa.length], 0, results);
return results;
}
public void find(char[] sa, int from, int[] split, int splits, List<String> words){
if (from == sa.length){
char[] word = new char[sa.length + splits -1];
int wordPos = 0, splitPos = 0;
for (int i = 0; i < sa.length; i++){
if(i == split[splitPos]){
word[wordPos++] = ' ';
splitPos++;
}
word[wordPos++] = sa[i];
}
words.add(new String(word));
return;
}
TriNode current = root;
for (int i = from; i < sa.length; i++){
current = current.nexts[sa[i] - 'a'];
if (current == null)
break;
if (current.isWord){
split[splits] = i + 1;
find(sa, i + 1, split, splits + 1, words);
}
}
}
}