Given a list of words (without duplicates), please write a program that returns all concatenated words in the given list of words.
A concatenated word is defined as a string that is comprised entirely of at least two shorter words in the given array.
Example:
Input: ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"]
Output: ["catsdogcats","dogcatsdog","ratcatdogcat"]
Explanation: "catsdogcats" can be concatenated by "cats", "dog" and "cats";
"dogcatsdog" can be concatenated by "dog", "cats" and "dog";
"ratcatdogcat" can be concatenated by "rat", "cat", "dog" and "cat".
Note:
- The number of elements of the given array will not exceed
10,000
- The length sum of elements in the given array will not exceed
600,000
. - All the input string will only include lower case letters.
- The returned elements order does not matter.
思路:先把所有字符串插入字典树,用isEnd标记字符串的结束。再遍历所有字符串,检查其是否在字典树中由2个以上字符串组成。
class TrieNode{//字典树节点
boolean isEnd=false;
TrieNode[] nodes=new TrieNode[26];//下标代表字母
}
public List<String> findAllConcatenatedWordsInADict(String[] words) {
TrieNode root=new TrieNode();
//插入字典树
for(String word:words){
TrieNode node=root;
for(int i=0;i<word.length();i++){
if(node.nodes[word.charAt(i)-'a']==null){
node.nodes[word.charAt(i)-'a']=new TrieNode();
}
node=node.nodes[word.charAt(i)-'a'];
if(i==word.length()-1){
node.isEnd=true;
}
}
}
List<String> list=new ArrayList<>();
//dfs
for(String word:words){
if(dfs(root,root,word,0,1)){
list.add(word);
}
}
return list;
}
//index:字符串下标,time,匹配到第几个子字符串
public boolean dfs(TrieNode node,TrieNode root,String word,int index,int time){
//如果isEnd=true下一次搜索
if(node.isEnd&&time>1&&index>=word.length()){
return true;
}
if(index<word.length()&&node.nodes[word.charAt(index)-'a']!=null){
if(node.nodes[word.charAt(index)-'a'].isEnd&&dfs(root,root,word,index+1,time+1)){
return true;
}
if(dfs(node.nodes[word.charAt(index)-'a'],root,word,index+1,time)){
return true;
}
}
return false;
}