我无法理解trie的概念。从“特里”维基百科条目我有这张图片:
如果我正确地看到这一点,则trie中的所有叶节点将拼出整个单词,并且所有父节点都保持通向最终叶节点的字符。所以,如果我有一个名为DigitalTreeNode的类,由
定义public class DigitalTreeNode {
public boolean isAWord;
public String wordToHere; (compiles all the characters in a word together)
public Map<String, DTN> children;
}
如果我想实现一个返回trie中最长单词的方法,它只需要在每个叶节点找到最长的单词?我如何实现如下方法:
public static String longestWord (DigitalTreeNode d);
我猜它涉及设置一个最长的String变量,递归遍历每个节点并检查它是否是一个单词,如果它是一个单词并且它的长度大于最长变量那么longest = newWordLength。但是,我不确定地图中的孩子们是如何适应的。我如何使用上述方法找到任何特里结构中最长的单词?
答案 0 :(得分:5)
叶节点通常不包含整个字符串(尽管它们可以),很多时候在一个特里,叶节点只包含一个'$'符号来表示这是字符串的结尾。
要查找特里结构中最长的单词,您可以在树上使用BFS,以便首先找到“最后”的叶子。 “最后一个叶子”是从BFS队列中弹出的最后一个元素(在弹出BFS算法后,空队列停止)。
要从这片叶子中获取实际的单词,你需要从叶子上回到根。 This thread讨论了如何做到这一点。
此解决方案为O(|S| * n)
,其中|S|
是字符串的平均长度,n
是DS中字符串的数量。
如果你可以操纵特里DS,我认为它可以做得更好(但这似乎不是这个问题中的问题)
伪码:
findLongest(trie):
//first do a BFS and find the "last node"
queue <- []
queue.add(trie.root)
last <- nil
map <- empty map
while (not queue.empty()):
curr <- queue.pop()
for each son of curr:
queue.add(son)
map.put(son,curr) //marking curr as the parent of son
last <- curr
//in here, last indicate the leaf of the longest word
//Now, go up the trie and find the actual path/string
curr <- last
str = ""
while (curr != nil):
str = curr + str //we go from end to start
curr = map.get(curr)
return str
答案 1 :(得分:0)
另一种实现方法是添加一个布尔值以表示它是否是单词的结尾和实际单词,如下所示:
public class TrieNode {
private HashMap<Character, TrieNode> children = new HashMap<>();
private boolean endOfWord;
private String actualWord;
//setter getter
}
在插入时,如果它是单词的结尾,则将boolean设置为true并设置实际单词
public void insert(String insert) {
HashMap<Character, TrieNode> parent = root.getChildren();
TrieNode child = null;
for (Character c : insert.toCharArray()) {
child = parent.containsKey(c) ? parent.get(c) : new TrieNode();
parent.put(c, child);
parent = child.getChildren();
}
if (child != null) {
child.setEndOfWord(true);
child.setActualWord(insert);
}
}
最后获取它,您只需进行BFS搜索,一旦有了该节点,便有了您要查找的实际单词。
public TrieNode findLongest() {
LinkedList<TrieNode> queue = new LinkedList();
queue.push(root);
TrieNode current = null;
while (!queue.isEmpty()) {
current = queue.pop();
if (current.getChildren() != null) {
for (TrieNode children : current.getChildren().values()) {
queue.push(children);
}
}
}
System.out.println(current.getActualWord()); // check here
return current;
}