Trie树_5-DoubleArrayTrieTree

Posted searchtosuggest

tags:

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

1、引言

  DoubleArrayTrieTree是使用双数组来保存状态节点和状态转移条件

2、实现

 状态节点:

 1 private class Node{
 2         
 3     private int base = 128;
 4     private T t;
 5         
 6     public Node() {
 7         // TODO Auto-generated constructor stub
 8     }
 9 
10     public int getBase() {
11         return base;
12     }
13 
14     public void setBase(int base) {
15         this.base = base;
16     }
17 
18     public T getT() {
19         return t;
20     }
21 
22     public void setT(T t) {
23         this.t = t;
24     }
25         
26     @Override
27     public String toString() {
28         return "base:" + base + "t:" + t;
29     }
30 }

  t保存节点的有效值,base为节点的状态转移基数

声明字段:

1 private List<Node> states = new ArrayList<>();
2 private List<Integer> checks = new ArrayList<>();

构造函数:

1 public DoubleArrayTrieTree() {
2     Node root = new Node();
3     this.states.add(root);
4 }

  数组状态变化:

status:
states:|0,128,null
checks:

  只有根节点,检查数组checks为空

字符串插入:

 1 @Override
 2 public void insert(String str, T t) {
 3     if(str != null && str.length() > 0) {
 4         byte[] bs = str.getBytes();
 5         int parent = 0;
 6         for(byte b : bs) {
 7             parent = this.insert(parent, b);
 8         }
 9         this.states.get(parent).setT(t);;
10     }
11 }
12     
13 private int insert(int parent, byte b) {
14     Node parentNode = this.states.get(parent);
15     int parentBase = parentNode.getBase();
16     int tempChildIndex = parentBase + b;
17     ensureSize(this.states, tempChildIndex);
18     ensureSize(this.checks, tempChildIndex);
19     Integer checkValue = this.checks.get(tempChildIndex);
20     if(checkValue == null) {
21         this.checks.set(tempChildIndex, parent);
22         this.states.set(tempChildIndex, new Node());
23     }else if (checkValue != parent) {
24         int maxIndex = Integer.MIN_VALUE;
25         List<Integer> children = new LinkedList<>();
26         for(int i = 0; i < this.checks.size(); i++) {
27             Integer childIndex = this.checks.get(i);
28             if(childIndex != null && childIndex == parent) {
29                 children.add(i);
30                 if(i > maxIndex) {
31                     maxIndex = i;
32                 }
33             }
34         }
35         children.add(tempChildIndex);
36         if(tempChildIndex > maxIndex) {
37             maxIndex = tempChildIndex;
38         }
39         int offset = this.ensureCheckValid(children, maxIndex);
40         parentNode.setBase(parentBase + offset);
41         for(int i = 0; i < children.size() - 1; i++) {
42             int originalIndex = children.get(i);
43             this.checks.set(originalIndex + offset, parent);
44             this.states.set(originalIndex + offset, this.states.get(originalIndex));
45             for(int j = 0; j < this.checks.size(); j++) {
46                 Integer originalCheckValue = this.checks.get(j);
47                 if(originalCheckValue != null && originalCheckValue == originalIndex) {
48                     this.checks.set(j, originalIndex + offset);
49                 }
50             }
51             this.checks.set(originalIndex, null);
52         }
53         tempChildIndex = tempChildIndex + offset;
54         this.checks.set(tempChildIndex, parent);
55         this.states.set(tempChildIndex, new Node());
56     }
57     return tempChildIndex;
58 }
59     
60     
61 private void ensureSize(List<?> list, int size) {
62     int originalSize = list.size() - 1;
63     if(size > originalSize) {
64         for(int i = 0; i < size - originalSize; i ++) {
65             list.add(null);
66         }
67     }
68 }
69     
70 private int ensureCheckValid(List<Integer> list, int maxIndex) {
71     int offset = 0;
72     while(true) {
73         int lastIndex = maxIndex + offset;
74         ensureSize(this.checks, lastIndex);
75         ensureSize(this.states, lastIndex);
76         if(this.checkValid(list, offset)) {
77             break;
78         }
79         offset++;
80     }
81     return offset;
82 }
83     
84     
85 private boolean checkValid(List<Integer> list, int offset) {
86     for(int originalIndex : list) {
87         if(this.checks.get(originalIndex + offset) != null) {
88             return false;
89         }
90     }
91     return true;
92 }

  states数组既要保存数字,也需要保存状态转移的条件,同样需要考虑不同节点存储的碰撞问题

  插入字符串:江南大学, 江南, 江边, 南方, 云南 过程中的三数组状态变化:

status:
states:|0,128,null|1,null,null|2,null,null|3,null,null|4,null,null|5,null,null|6,null,null|7,null,null|8,null,null|9,null,null|10,null,null|11,null,null|12,null,null|13,128,null|14,null,null|15,null,null|16,null,null|17,null,null|18,null,null|19,null,null|20,null,null|21,null,null|22,null,null|23,130,null|24,null,null|25,null,null|26,null,null|27,null,null|28,null,null|29,null,null|30,null,null|31,128,null|32,null,null|33,null,null|34,null,null|35,null,null|36,128,null|37,null,null|38,128,江南大学|39,131,null|40,null,null|41,null,null|42,null,null|43,null,null|44,null,null|45,128,null|46,null,null|47,null,null|48,null,null|49,128,null|50,null,null|51,null,null|52,null,null|53,null,null|54,null,null|55,null,null|56,null,null|57,null,null|58,null,null|59,null,null|60,null,null|61,null,null|62,null,null|63,null,null|64,null,null|65,null,null|66,null,null|67,null,null|68,null,null|69,null,null|70,null,null|71,null,null|72,null,null|73,null,null|74,null,null|75,null,null|76,null,null|77,null,null|78,null,null|79,null,null|80,null,null|81,null,null|82,null,null|83,null,null|84,null,null|85,null,null|86,null,null|87,null,null|88,null,null|89,null,null|90,null,null|91,null,null|92,null,null|93,null,null|94,null,null|95,null,null|96,null,null|97,null,null|98,null,null|99,null,null|100,null,null|101,128,null|102,128,null|103,128,null|104,128,null
checks:|0,null |1,null |2,null |3,null |4,null |5,null |6,null |7,null |8,null |9,null |10,null |11,null |12,null |13,101 |14,null |15,null |16,null |17,null |18,null |19,null |20,null |21,null |22,null |23,13 |24,null |25,null |26,null |27,null |28,null |29,null |30,null |31,49 |32,null |33,null |34,null |35,null |36,103 |37,null |38,45 |39,36 |40,null |41,null |42,null |43,null |44,null |45,104 |46,null |47,null |48,null |49,102 |50,null |51,null |52,null |53,null |54,null |55,null |56,null |57,null |58,null |59,null |60,null |61,null |62,null |63,null |64,null |65,null |66,null |67,null |68,null |69,null |70,null |71,null |72,null |73,null |74,null |75,null |76,null |77,null |78,null |79,null |80,null |81,null |82,null |83,null |84,null |85,null |86,null |87,null |88,null |89,null |90,null |91,null |92,null |93,null |94,null |95,null |96,null |97,null |98,null |99,null |100,null |101,31 |102,0 |103,23 |104,39 

status:
states:|0,128,null|1,null,null|2,null,null|3,null,null|4,null,null|5,null,null|6,null,null|7,null,null|8,null,null|9,null,null|10,null,null|11,null,null|12,null,null|13,128,null|14,null,null|15,null,null|16,null,null|17,null,null|18,null,null|19,null,null|20,null,null|21,null,null|22,null,null|23,130,江南|24,null,null|25,null,null|26,null,null|27,null,null|28,null,null|29,null,null|30,null,null|31,128,null|32,null,null|33,null,null|34,null,null|35,null,null|36,128,null|37,null,null|38,128,江南大学|39,131,null|40,null,null|41,null,null|42,null,null|43,null,null|44,null,null|45,128,null|46,null,null|47,null,null|48,null,null|49,128,null|50,null,null|51,null,null|52,null,null|53,null,null|54,null,null|55,null,null|56,null,null|57,null,null|58,null,null|59,null,null|60,null,null|61,null,null|62,null,null|63,null,null|64,null,null|65,null,null|66,null,null|67,null,null|68,null,null|69,null,null|70,null,null|71,null,null|72,null,null|73,null,null|74,null,null|75,null,null|76,null,null|77,null,null|78,null,null|79,null,null|80,null,null|81,null,null|82,null,null|83,null,null|84,null,null|85,null,null|86,null,null|87,null,null|88,null,null|89,null,null|90,null,null|91,null,null|92,null,null|93,null,null|94,null,null|95,null,null|96,null,null|97,null,null|98,null,null|99,null,null|100,null,null|101,128,null|102,128,null|103,128,null|104,128,null
checks:|0,null |1,null |2,null |3,null |4,null |5,null |6,null |7,null |8,null |9,null |10,null |11,null |12,null |13,101 |14,null |15,null |16,null |17,null |18,null |19,null |20,null |21,null |22,null |23,13 |24,null |25,null |26,null |27,null |28,null |29,null |30,null |31,49 |32,null |33,null |34,null |35,null |36,103 |37,null |38,45 |39,36 |40,null |41,null |42,null |43,null |44,null |45,104 |46,null |47,null |48,null |49,102 |50,null |51,null |52,null |53,null |54,null |55,null |56,null |57,null |58,null |59,null |60,null |61,null |62,null |63,null |64,null |65,null |66,null |67,null |68,null |69,null |70,null |71,null |72,null |73,null |74,null |75,null |76,null |77,null |78,null |79,null |80,null |81,null |82,null |83,null |84,null |85,null |86,null |87,null |88,null |89,null |90,null |91,null |92,null |93,null |94,null |95,null |96,null |97,null |98,null |99,null |100,null |101,31 |102,0 |103,23 |104,39 

status:
states:|0,128,null|1,null,null|2,null,null|3,null,null|4,null,null|5,null,null|6,null,null|7,null,null|8,null,null|9,null,null|10,null,null|11,null,null|12,null,null|13,128,null|14,null,null|15,null,null|16,null,null|17,null,null|18,null,null|19,null,null|20,null,null|21,null,null|22,null,null|23,130,江南|24,null,null|25,null,null|26,null,null|27,null,null|28,null,null|29,null,null|30,null,null|31,132,null|32,null,null|33,null,null|34,null,null|35,null,null|36,128,null|37,null,null|38,128,江南大学|39,131,null|40,null,null|41,null,null|42,null,null|43,null,null|44,null,null|45,128,null|46,null,null|47,null,null|48,null,null|49,128,null|50,null,null|51,null,null|52,null,null|53,null,null|54,null,null|55,null,null|56,null,null|57,128,江边|58,null,null|59,null,null|60,null,null|61,null,null|62,128,null|63,null,null|64,null,null|65,null,null|66,null,null|67,null,null|68,null,null|69,null,null|70,null,null|71,null,null|72,null,null|73,null,null|74,null,null|75,null,null|76,null,null|77,null,null|78,null,null|79,null,null|80,null,null|81,null,null|82,null,null|83,null,null|84,null,null|85,null,null|86,null,null|87,null,null|88,null,null|89,null,null|90,null,null|91,null,null|92,null,null|93,null,null|94,null,null|95,null,null|96,null,null|97,null,null|98,null,null|99,null,null|100,null,null|101,128,null|102,128,null|103,128,null|104,128,null|105,128,null|106,null,null|107,null,null|108,128,null
checks:|0,null |1,null |2,null |3,null |4,null |5,null |6,null |7,null |8,null |9,null |10,null |11,null |12,null |13,105 |14,null |15,null |16,null |17,null |18,null |19,null |20,null |21,null |22,null |23,13 |24,null |25,null |26,null |27,null |28,null |29,null |30,null |31,49 |32,null |33,null |34,null |35,null |36,103 |37,null |38,45 |39,36 |40,null |41,null |42,null |43,null |44,null |45,104 |46,null |47,null |48,null |49,102 |50,null |51,null |52,null |53,null |54,null |55,null |56,null |57,62 |58,null |59,null |60,null |61,null |62,108 |63,null |64,null |65,null |66,null |67,null |68,null |69,null |70,null |71,null |72,null |73,null |74,null |75,null |76,null |77,null |78,null |79,null |80,null |81,null |82,null |83,null |84,null |85,null |86,null |87,null |88,null |89,null |90,null |91,null |92,null |93,null |94,null |95,null |96,null |97,null |98,null |99,null |100,null |101,null |102,0 |103,23 |104,39 |105,31 |106,null |107,null |108,31 

status:
states:|0,128,null|1,null,null|2,null,null|3,null,null|4,null,null|5,null,null|6,null,null|7,null,null|8,null,null|9,null,null|10,null,null|11,null,null|12,null,null|13,128,null|14,129,null|15,null,null|16,null,null|17,null,null|18,null,null|19,null,null|20,null,null|21,null,null|22,129,null|23,130,江南|24,132,null|25,null,null|26,null,null|27,null,null|28,null,null|29,null,null|30,null,null|31,132,null|32,null,null|33,null,null|34,null,null|35,null,null|36,128,null|37,null,null|38,128,江南大学|39,131,null|40,null,null|41,null,null|42,null,null|43,null,null|44,null,null|45,128,null|46,null,null|47,null,null|48,null,null|49,128,null|50,null,null|51,null,null|52,null,null|53,null,null|54,null,null|55,null,null|56,null,null|57,128,江边|58,128,南方|59,null,null|60,null,null|61,null,null|62,128,null|63,null,null|64,null,null|65,null,null|66,null,null|67,null,null|68,null,null|69,null,null|70,null,null|71,null,null|72,null,null|73,null,null|74,null,null|75,null,null|76,null,null|77,null,null|78,null,null|79,null,null|80,null,null|81,null,null|82,null,null|83,null,null|84,null,null|85,null,null|86,null,null|87,null,null|88,null,null|89,null,null|90,null,null|91,null,null|92,null,null|93,null,null|94,null,null|95,null,null|96,null,null|97,null,null|98,null,null|99,null,null|100,null,null|101,129,null|102,128,null|103,128,null|104,128,null|105,128,null|106,128,null|107,null,null|108,128,null
checks:|0,null |1,null |2,null |3,null |4,null |5,null |6,null |7,null |8,null |9,null |10,null |11,null |12,null |13,105 |14,101 |15,null |16,null |17,null |18,null |19,null |20,null |21,null |22,106 |23,13 |24,14 |25,null |26,null |27,null |28,null |29,null |30,null |31,49 |32,null |33,null |34,null |35,null |36,103 |37,null |38,45 |39,36 |40,null |41,null |42,null |43,null |44,null |45,104 |46,null |47,null |48,null |49,102 |50,null |51,null |52,null |53,null |54,null |55,null |56,null |57,62 |58,22 |59,null |60,null |61,null |62,108 |63,null |64,null |65,null |66,null |67,null |68,null |69,null |70,null |71,null |72,null |73,null |74,null |75,null |76,null |77,null |78,null |79,null |80,null |81,null |82,null |83,null |84,null |85,null |86,null |87,null |88,null |89,null |90,null |91,null |92,null |93,null |94,null |95,null |96,null |97,null |98,null |99,null |100,null |101,0 |102,0 |103,23 |104,39 |105,31 |106,24 |107,null |108,31 

status:
states:|0,128,null|1,null,null|2,null,null|3,null,null|4,null,null|5,null,null|6,null,null|7,null,null|8,null,null|9,null,null|10,null,null|11,null,null|12,null,null|13,128,null|14,129,null|15,130,null|16,null,null|17,134,null|18,null,null|19,null,null|20,null,null|21,null,null|22,129,null|23,130,江南|24,132,null|25,128,云南|26,null,null|27,null,null|28,null,null|29,null,null|30,null,null|31,132,null|32,null,null|33,null,null|34,null,null|35,null,null|36,128,null|37,null,null|38,128,江南大学|39,131,null|40,null,null|41,null,null|42,null,null|43,null,null|44,null,null|45,128,null|46,null,null|47,null,null|48,null,null|49,128,null|50,null,null|51,null,null|52,null,null|53,null,null|54,null,null|55,null,null|56,null,null|57,128,江边|58,128,南方|59,128,null|60,null,null|61,null,null|62,128,null|63,null,null|64,null,null|65,null,null|66,null,null|67,null,null|68,null,null|69,null,null|70,null,null|71,null,null|72,null,null|73,null,null|74,null,null|75,null,null|76,null,null|77,null,null|78,null,null|79,null,null|80,null,null|81,null,null|82,null,null|83,null,null|84,null,null|85,null,null|86,null,null|87,null,null|88,null,null|89,null,null|90,null,null|91,null,null|92,null,null|93,null,null|94,null,null|95,null,null|96,null,null|97,null,null|98,null,null|99,null,null|100,129,null|101,129,null|102,128,null|103,128,null|104,128,null|105,128,null|106,128,null|107,130,null|108,128,null
checks:|0,null |1,null |2,null |3,null |4,null |5,null |6,null |7,null |8,null |9,null |10,null |11,null |12,null |13,105 |14,101 |15,107 |16,null |17,59 |18,null |19,null |20,null |21,null |22,106 |23,13 |24,14 |25,15 |26,null |27,null |28,null |29,null |30,null |31,49 |32,null |33,null |34,null |35,null |36,103 |37,null |38,45 |39,36 |40,null |41,null |42,null |43,null |44,null |45,104 |46,null |47,null |48,null |49,102 |50,null |51,null |52,null |53,null |54,null |55,null |56,null |57,62 |58,22 |59,100 |60,null |61,null |62,108 |63,null |64,null |65,null |66,null |67,null |68,null |69,null |70,null |71,null |72,null |73,null |74,null |75,null |76,null |77,null |78,null |79,null |80,null |81,null |82,null |83,null |84,null |85,null |86,null |87,null |88,null |89,null |90,null |91,null |92,null |93,null |94,null |95,null |96,null |97,null |98,null |99,null |100,0 |101,0 |102,0 |103,23 |104,39 |105,31 |106,24 |107,17 |108,31 

  字符串查询:

@Override
public T search(String str) {
    if(str != null && str.length() > 0) {
        byte[] bs = str.getBytes();
        int parent = 0;
        for(byte b : bs) {
            parent = this.search(parent, b);
        }
        if(parent >= 0) {
            Node node = this.states.get(parent);
            if(node != null) {
                return node.getT();
            }
        }
    }
    return null;
}
    
private int search(int parent, byte b) {
    if(parent >= 0 && parent < this.states.size()) {
        Node parentNode =  this.states.get(parent);
        int childIndex = parentNode.getBase() + b;
        Integer checkValue = this.checks.get(childIndex);
        if(checkValue != null && checkValue == parent) {
            return childIndex;
        }
    }
    return -1;
}

  查询逻辑比较简单

 

前缀查询:

@Override
public List<T> prefixSearch(String prefix) {
    List<T> result = new LinkedList<>();
    if(prefix != null && prefix.length() > 0) {
        byte[] bs = prefix.getBytes();
        int parent = 0;
        for(int i = 0; i < bs.length; i++) {
            parent = this.search(parent, bs[i]);
        }
        if(parent > 0) {
            List<Integer> q = new LinkedList<>();
            q.add(parent);
            while (q.size() > 0) {
                int head = q.remove(0);
                T t = this.states.get(head).getT();
                if(t != null) {
                    result.add(t);
                }
                for(int i = 0; i < this.checks.size(); i++) {
                    Integer checkValue = this.checks.get(i);
                    if(checkValue != null && checkValue == head) {
                        q.add(i);
                    }
                }
            }
        }
    }
    return result;
}

使用队列的方式,遍历前缀查询

3、总结

  DoubleArrayTrieTree相对于TripleArrayTrieTree少了一个数组,内存开销进一步减少

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

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

Trie树_3-MapBaseTrieTree

Trie树_4-TripleArrayTrieTree

Trie树_5-DoubleArrayTrieTree

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

PHP 生成 Trie 树

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