双数组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
从图中可以看出,下标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>>