现在的位置: 首页 > 综合 > 正文

双数组trie原理

2017年12月13日 ⁄ 综合 ⁄ 共 2000字 ⁄ 字号 评论关闭

双数 组 Trie(Double-ArrayTrie) 的数据结构是两个整数数组,一个是base[],一个是check
这个算法的本质就是将Trie树结构简化为两个线性数组,如图2所示。
base数组和数组中的元素是一一对应的,base数组中的每一个元素相当于Trie树的一个节点,其值做状态转移的基值,check值相当于校验值,用于检查该状态是否存在。对于从状态
s到状态t的一个转移,必须满足如下两个条件:
1.base[s]+c=t
2.check[ t] =s
其中c是输入变量。

数组构造完成之后,要查找一个关键码Ab是很快,只需要一步加法,即只需判断check[base[A]+b]是否等于A.状态A有个基值,为base[A],则Ab所在的节点应该为基值+输入状态,即base[A]+b,可以这么认为,Ab的节点为base[A]+b,同样这个节点也存在相应的基值。

同理要查找abc是否在词典中,只需判断check[base[base[a]+b]+c]是否等于base[a]+b

双数组trie树的构造过程,稍微麻烦点,详细请参考:http://linux.thai.net/~thep/datrie/datrie.html

假设这样一个场景,ab,ac,ae已经放入trie中,这时要插入ad, base[ base[a]+d ] !=0,说明ad节点的位置已经被其他的词占了,譬如是ec。这个时候要调整a的基值,即base[a].如果要调节base[a]就要考虑到,ab,ac,ae的值要改变,同时abe的值也会改变。算法如下:

其中,s就是例子中的a,本来base[a]=t,但是插入ad时,位置已经被其他词占了,譬如ec,所以这时要调整base[a]的值,调整为base[a] = b,至于b是如果得到的,请继续研究。。。。

因为现在base[s]=b,所以词sb,sc,se所对应的节点下标要改变,如行2所示;本来sb,sc,se对应的下标,即节点为base[s]+b,base[s]+c,base[s]+e,现在要改为b+b,b+c,b+e

因为sb,se,sc移到了新位置,所以check要更新,如行1所示;指示sb,sc,se的新节点为b+b,b+c,b+e,但是他们的上一个节点还是s


改变sc的值,那scd的节点也要变化,要主要到scd的节点对应的下标没有变化,base[base[s]+c] +d ,虽然s的基值变为了b,但是sc的基值还是不变,但是ac的下表变了,所以要更新acd上一个状态对应的下标,只要更新check[base[ base[s]+c]+d],使其指向下标b+c;如行3 所示


Procedure Relocate(s : state; b : base_index)
{ Move base for state s to a new place beginning at b }
begin
    foreach input character c for the state s
    { i.e. foreach c such that check[base[s] + c]] = s }
    begin
        check[b + c] := s;     { mark owner }//1
        base[b + c] := base[base[s] + c];     { copy data }//2
        { the node base[s] + c is to be moved to b + c;
          Hence, for any i for which check[i] = base[s] + c, update check[i] to b + c }
        foreach input character d for the node base[s] + c
        begin
            check[base[base[s] + c] + d] := b + c//3
        end;
        check[base[s] + c] := none     { free the cell }
    end;
    base[s] := b
end


Double-Array Relocation

从图中可以看出,下标s的基值变为b,即虚线所指

对应sc的下标从t变为t',要更新check[t'] = s,check[u] = t'



//////////////////////////////////////////////////////////////////////

笔试题:

请设计一个字典。以字符串为索引,存储用户定义的定长结构。要求有增、删、查、改的功能。已经给定一个函数,可以由字符串映射到一个签名,每个签名由两个unsigned
int类型组成。假设每一个字符串能够对应唯一的一个签名,完全没有重复(或者重复的概率可以忽略),并且签名分布足够均匀。


最直接的想法就是构造一个两层的trie树

还可以用hash来做,用第一个unsigned int作为hash的key,将key相等的词的第二个unsigned int安装顺序排序,这样可以用二分查找法查找

map<int, map<int, data>>


抱歉!评论已关闭.