Trie树_3-MapBaseTrieTree

Posted searchtosuggest

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Trie树_3-MapBaseTrieTree相关的知识,希望对你有一定的参考价值。

1、引言

  MapBaseTrieTree是基于Map数据结构保存状态转移条件实现的trie树。

2、实现

  状态节点:

 1 private class Node{
 2     private T t;
 3     private Map<Byte,  Node> next = new HashMap<>();
 4         
 5     public Node() {
 6         // TODO Auto-generated constructor stub
 7     }
 8 
 9     public T getT() {
10         return t;
11     }
12 
13     public void setT(T t) {
14         this.t = t;
15     }
16 
17     public Map<Byte, Node> getNext() {
18         return next;
19     }        
20 }

  其中t为状态节点中的有效信息,next中保存着该状态节点向下一个状态节点的转移条件

声明字段:

1 private Node root;

  root为trie树的根节点

构造函数:

1 public MapBaseTrieTree() {
2     this.root = new Node();
3 }

  构造函数只是初始化根节点

字符串插入:

 1 @Override
 2 public void insert(String str, T t) {
 3     if(str != null && str.length() > 0) {
 4         byte[] bs = str.getBytes();
 5         Node parent = this.root;
 6         for(int i = 0; i < bs.length; i++) {
 7             parent = this.insert(parent, bs[i]);
 8         }
 9         parent.setT(t);
10     }    
11 }
12     
13 private Node insert(Node parent, byte b) {
14     Node child = parent.getNext().getOrDefault(b, null);
15     if(child == null) {
16         child = new Node();
17         parent.getNext().put(b, child);
18     }
19     return child;
20 }

  将字符串转为字节数组的形式,字节的值为状态转移字典next中key,key对应的值为下一个状态节点,next字典不包含key时,新建一个状态节点;在最后的字节插入后对应的状态节点中插入有效值t。

字符串检索:

 1 @Override
 2 public T search(String str) {
 3     if(str != null && str.length() > 0) {
 4         byte[] bs = str.getBytes();
 5         Node parent = this.root;
 6         for(int i = 0; i < bs.length; i++) {
 7             parent = this.search(parent, bs[i]);
 8         }
 9         if(parent != null) {
10             return parent.getT();
11         }
12     }
13     return null;
14 }
15     
16 private Node search(Node parent, byte b) {
17     if(parent != null) {
18         return parent.getNext().getOrDefault(b, null);
19     }
20     return null;
21 }

  检索时和插入使用一样的方法

 

前缀检索:

 1 @Override
 2 public List<T> prefixSearch(String prefix) {
 3     List<T> results = new LinkedList<>();
 4     if(prefix != null && prefix.length() > 0) {
 5         byte[] bs = prefix.getBytes();
 6         Node parent = this.root;
 7         for(int i = 0; i < bs.length; i++) {
 8             parent = this.search(parent, bs[i]);
 9         }
10         if(parent != null) {
11             List<Node> q = new LinkedList<>();
12             q.add(parent);
13             while(q.size() > 0) {
14                 Node head = q.remove(0);
15                 T t = head.getT();
16                 if(t != null) {
17                     results.add(t);
18                 }
19                 q.addAll(head.getNext().values());
20             }
21         }
22     }
23     return results;
24 }

3、总结

  MapBaseTrieTree实现简单,字符串插入和查询速度快。

参考: https://github.com/pythonerleilei/Search/blob/master/src/seach/data_structure/tree/impl/MapBaseTrieTree.java

以上是关于Trie树_3-MapBaseTrieTree的主要内容,如果未能解决你的问题,请参考以下文章

hihocoder_1014: Trie树(Trie树模板题)

Trie树

Trie树_4-TripleArrayTrieTree

Trie树_5-DoubleArrayTrieTree

BZOJ_3012_[Usaco2012 Dec]First!_trie树+拓扑排序

[H字典树] lc1938. 查询最大基因差(trie总结+dfs离线搜索+离线处理+周赛250_4)