zoukankan      html  css  js  c++  java
  • DoubleArray Trie快速入门

    Double-Array Trie快速入门

    shiqi.cui<cuberub@gmail.com>
    May 24, 2009

    1. Trie

    Trie是一种搜索树,因“Retrieval”而得名。在以Trie树组织的词典里,所有词条的公共前缀是压缩存储的,即只会存储一份,所以又称前缀树。如图所示:

    Trie树结构示意图

    Trie可以理解为确定有限状态自动机,即DFA。在Trie树中,每个节点表示一个状态,每条边表示一个字符,从根节点到叶子节点经过的边即表示一个词条。查找一个词条最多耗费的时间只受词条长度影响,因此Trie的查找性能是很高的,跟哈希算法的性能相当。

    2. Trie存储方式

    Trie可以按照树的方式存储。每个节点包含n个指针,分别指向n个后续节点,每条边对应着一个输入字符。这样,每个节点的指针个数是跟字符表的大小相关的。如果按照链表的方式组织n个指针,查询的效率会比较低;如果以定长数组表示n个指针,占用的空间会比较大,基本是不可接受的。

    Trie也可以按照DFA的方式存储,即表示为转移矩阵。行表示状态,列表示输入字符,(行, 列)位置表示转移状态。这种方式的查询效率很高,但由于稀疏的现象严重,空间利用效率很低。也可以采用压缩的存储方式即链表来表示状态转移,但查询效率无法满足要求。

    为了解决上面的问题,有学者依次设计出了Four-Array Trie,Triple-Array Trie和Double-Array Trie结构,其得名源于内部采用的数组的个数。

    3. Double-Array Trie

    Double-Array Trie包含base和check两个数组。base数组的每个元素表示一个Trie节点,即一个状态;check数组表示某个状态的前驱状态。

    base和check的关系满足下述条件:

    base[s] + c = t

    check[t] = s

    其中,s是当前状态的下标,t是转移状态的下标,c是输入字符的数值。如图所示:

    4. 查询过程

    根据上述公式,查找某个字符串就非常简单。

    假设初始状态为t0,字符序列是(c1, c2, …, cn)。那么,输入c1后的状态为t1 = base[t0] + c1,以此类推。

    如果到某个状态是不合法的,那么查询失败;如果转到状态tn = base[tn-1] + c,并且tn是结束状态,那么查询成功;如果tn不是结束状态,那么查询失败。

    5. 构建过程

    首先,初始化base和check数组,元素默认值是0。随机确定初始状态t0及其base值,如t0=0, base[t0]=1。

    对于插入词条,计算输入每个字符后的base位置。

    如果该位置为空,则表示该位置可以插入,然后转到下一个字符;

    如果该位置已有值,表示该位已经被其他的状态占用,这样需要调整其前驱状态的base值,以保证状态不会冲突,这个过程称为relocate。

    6. 参考文档

    1. http://linux.thai.net/~thep/datrie/datrie.html

  • 相关阅读:
    POJ 1236 Network of Schools(强连通分量缩点求根节点和叶子节点的个数)
    文本编辑器vim和gedit
    Ubuntu安装tensorflow
    剑指offer——python【第29题】最小的K个数
    剑指offer——python【第30题】连续子数组的最大和
    剑指offer——python【第37题】数字在排序数组中出现的次数
    剑指offer——python【第28题】数组 中出现次数超过一半的数字
    剑指offer——python【第31题】整数1出现的次数
    剑指offer——python【第54题】字符流中第一个不重复的字符
    剑指offer——python【第40题】数组中只出现一次的数字
  • 原文地址:https://www.cnblogs.com/lexus/p/2416333.html
Copyright © 2011-2022 走看看