class TrieNode {
TrieNode[] children;
boolean hasWord;
boolean isComb;
boolean isAdd;
String word;
public TrieNode() {
children = new TrieNode[26];
hasWord = false;
isComb = false;
isAdd = false;
}
}
public class Solution {
public TrieNode buildTrieTree(String[] words) {
TrieNode root = new TrieNode();
for (String word : words) {
TrieNode temp = root;
if (word.length() == 0) continue; //[""]
for (char c : word.toCharArray()) {
int idx = c - 'a';
if (temp.children[idx] == null) temp.children[idx] = new TrieNode();
temp = temp.children[idx];
}
temp.hasWord = true;
temp.word = word;
}
return root;
}
public List<String> findAllConcatenatedWordsInADict(String[] words) {
TrieNode root = buildTrieTree(words);
List<String> res = new ArrayList<String>();
dfs(root, root, 0, res);
return res;
}
public void dfs(TrieNode root, TrieNode node, int times, List<String> res) {
if (node.hasWord && !node.isAdd && times > 1) {
res.add(node.word);
node.isAdd = true;
node.isComb = true;
}
helper(root, node, root, times, res);
}
public void helper(TrieNode root, TrieNode node1, TrieNode node2, int times, List<String> res) {
if (node2.isComb) return;
if (node2.hasWord) {
dfs(root, node1, times + 1, res);
}
for (int i = 0; i < 26; i++) {
if (node1.children[i] != null && node2.children[i] != null) {
helper(root, node1.children[i], node2.children[i], times, res);
}
}
}
}
public class Solution {
public List<String> findAllConcatenatedWordsInADict(String[] words) {
List<String> res = new ArrayList<>();
if(words == null || words.length == 0) return res;
TrieNode root = new TrieNode();
for(String s : words) add(root, s);
for(String s : words){
if(dfs(root, root, s, 0)) res.add(s);
}
return res;
}
private boolean dfs(TrieNode root, TrieNode cur, String s, int index){
if(index == s.length()) return cur.word != null && cur.word != s;
if(cur.children[s.charAt(index)-'a'] == null) return false;
if(cur.children[s.charAt(index)-'a'].word != null && dfs(root, root, s, index+1)) return true;
return dfs(root, cur.children[s.charAt(index)-'a'], s, index+1);
}
class TrieNode{
String word;
TrieNode[] children;
TrieNode(){
word = null;
children = new TrieNode[26];
}
}
private void add(TrieNode root, String s){
if(s.length()==0) return;
TrieNode cur = root;
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(cur.children[c-'a'] == null) cur.children[c-'a'] = new TrieNode();
cur = cur.children[c-'a'];
}
cur.word = s;
}
}