给定一个不含重复单词的列表,编写一个程序,返回给定单词列表中所有的连接词。
连接词的定义为:一个字符串完全是由至少两个给定数组中的单词组成的。
示例:
输入: ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"]
输出: ["catsdogcats","dogcatsdog","ratcatdogcat"]
解释: "catsdogcats"由"cats", "dog" 和 "cats"组成;
"dogcatsdog"由"dog", "cats"和"dog"组成;
"ratcatdogcat"由"rat", "cat", "dog"和"cat"组成。
说明:
给定数组的元素总数不超过 10000。
给定数组中元素的长度总和不超过 600000。
所有输入字符串只包含小写字母。
不需要考虑答案输出的顺序。
思路:
方法一:暴力,,开了一个list,用来存储上一次能匹配到的所有位置。然后我们通过暴力遍历可以判断出当前位置能否匹配到。
class Solution {
public List findAllConcatenatedWordsInADict(String[] words) {
Map map=new HashMap<>();
List ans=new ArrayList<>();
List list=new ArrayList<>();
for(int i=0;i0 && list.get(list.size()-1)==words[i].length()-1)
ans.add(words[i]);
}
return ans;
}
}
方法二:优雅的暴力,set+爆搜
class Solution {
private Set st=new HashSet<>();
public List findAllConcatenatedWordsInADict(String[] words) {
st.addAll(Arrays.asList(words));
List ans=new ArrayList<>(words.length);
for(String word : words) {
if(dfs(word,0,0))
ans.add(word);
}
return ans;
}
private boolean dfs(String word,int idx,int cnt) {
if(idx==word.length()) return cnt>1;
for(int i=idx;i
方法三:前缀树(字典树)
class Solution {
class Trie{
private TreeNode root;
class TreeNode{
String val;
TreeNode[] children;
public TreeNode() {
this.val=null;
this.children=new TreeNode[26];
}
}
Trie() {
this.root=new TreeNode();
}
private void insert(String word) {
TreeNode cur=root;
for(int i=0;i findAllConcatenatedWordsInADict(String[] words) {
Trie trie=new Trie();
for(String word : words)
trie.insert(word);
List ans=new ArrayList<>(words.length);
for(String word : words)
if(trie.search(word,0))
ans.add(word);
return ans;
}
}