472. 连接词
给你一个 不含重复 单词的字符串数组 words ,请你找出并返回 words 中的所有 连接词 。
连接词 定义为:一个完全由给定数组中的至少两个较短单词组成的字符串。
示例 1:
输入:words = ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"]
输出:["catsdogcats","dogcatsdog","ratcatdogcat"]
解释:"catsdogcats" 由 "cats", "dog" 和 "cats" 组成;
"dogcatsdog" 由 "dog", "cats" 和 "dog" 组成;
"ratcatdogcat" 由 "rat", "cat", "dog" 和 "cat" 组成。
示例 2:
输入:words = ["cat","dog","catdog"]
输出:["catdog"]
提示:
- 1 < = w o r d s . l e n g t h < = 1 0 4 1 <= words.length <= 10^4 1<=words.length<=104
- 0 <= words[i].length <= 1000
- words[i] 仅由小写字母组成
- 0 < = s u m ( w o r d s [ i ] . l e n g t h ) < = 1 0 5 0 <= sum(words[i].length) <= 10^5 0<=sum(words[i].length)<=105
题解
字典树+DFS
class Solution {
Trie trie = new Trie();
public List<String> findAllConcatenatedWordsInADict(String[] words) {
List<String> ans = new ArrayList<>();
Arrays.sort(words, (a, b) -> a.length() - b.length()); // 按字符串长度排序
for(int i = 0; i < words.length; i++){
String word = words[i];
if(word.length() == 0) continue;
if(dfs(word, 0)){
ans.add(word);
}else{
insert(word); // 不是连接词就将其加入字典树
}
}
return ans;
}
public boolean dfs(String word, int start){
if(word.length() == start){ // 遍历完整个字符串
return true;
}
Trie node = trie;
for(int i = start; i < word.length(); i++){
char ch = word.charAt(i);
int idx = ch - 'a';
node = node.children[idx];
if(node == null) return false; // 字典树中不存在当前单词
if(node.isEnd){ // 当前单词的末尾
if(dfs(word, i + 1)){ // 进入下一个单词遍历
return true;
}
}
}
return false;
}
public void insert(String word){ // 向字典树中插入单词
Trie node = trie;
for(int i = 0; i < word.length(); i++){
char ch = word.charAt(i);
int idx = ch - 'a';
if(node.children[idx] == null){
node.children[idx] = new Trie();
}
node = node.children[idx];
}
node.isEnd = true;
}
}
// 定义字典树类
class Trie{
Trie[] children;
boolean isEnd;
public Trie(){
children = new Trie[26];
isEnd = false;
}
}