题目
给你一个 不含重复 单词的字符串数组 words ,请你找出并返回 words 中的所有 连接词
。
连接词
定义为:一个完全由给定数组中的至少两个较短单词组成的字符串。
解题思路
字典树+DFS。这里我们定义非连接词为 连接子串
。
首先对于连接词,其长度必定比每一个连接字串的长度要长。对于这个题,我们可以先按照长度的升序,对所有字符串进行排序。对于排完序后的字符串,第 i
个字符串如果是连接词,那么其连接子串必定在前 i - 1
个字符串中。我们可以构建一个实时更新的字典树,我们希望把所有连接字串加入字典树,之后如果遇到连接词,就可以在字典树中进行判断。那么我们对排完序后的数组进行遍历,先用DFS在字典树中判断其是否为连接词,如果是那么就加入 ans
中,如果不是,那么将其加入字典树中。
代码
class Trie {
public static final int MAX_LENGTH = 26;
public Trie[] next;
public boolean isEnd;
public Trie() {
next = new Trie[26];
isEnd = false;
}
public void insert(String word) {
int length = word.length();
Trie nowNode = this;
for (int i = 0; i < length; i++) {
int index = word.charAt(i) - 'a';
if (nowNode.next[index] == null) {
nowNode.next[index] = new Trie();
}
nowNode = nowNode.next[index];
}
nowNode.isEnd = true;
}
}
class Solution {
public List<String> findAllConcatenatedWordsInADict(String[] words) {
Trie trie = new Trie();
List<String> ans = new ArrayList<>();
Arrays.sort(words, (a, b) -> a.length() - b.length());
for (String word : words) {
if (word.length() == 0) continue;
if (dfs(word, 0, trie)) ans.add(word);
else trie.insert(word);
}
return ans;
}
public boolean dfs(String word, int pos, Trie trie) {
if (word.length() == pos) return true;
Trie nowNode = trie;
for (int i = pos; i < word.length(); i++) {
int index = word.charAt(i) - 'a';
if (nowNode.next[index] == null) return false;
nowNode = nowNode.next[index];
if (nowNode.isEnd) {
if (dfs(word, i + 1, trie)) return true;
}
}
return false;
}
}