双数组trie树实现的第一篇论文,日本人JUN-ICHI AOE 1989年撰写的.
大概看完,简单记录下,可能有不准确的地方.
trie树有静态和动态两种,静态的直接就是一个DFA,没什么好说的,使用内存什么都比较确定而且最少.动态的可以支持删除和插入,双数组做法就是一种实现.
为了保证字典中所有词都不是其他词的前缀,在每个词后面加上#标识.双数组是指base和check这两个数组,base数组和check数组,一个状态用一个数字表示(这个数字是从1开始数),一个状态转移s->t(边为‘a‘),表示为:
base[s] + ‘a‘ = t check[t] = s
base[s] = 0 && check[s] = 0则表示状态s不存在.
这样看起来这两个数组中很可能存在大量的空洞,但是这里做了一个优化,对于可以通过前缀判断是哪个词的那个状态,base数组保存的是一个负数值,这个负值的相反数是一个tail数组的索引,这个数组该索引出保存尾部这些字符串(所以实际上加上这个tail数组还是三个数组了),减少了状态数,也就减少了对base和check数组的占用,插入新词时如果按照base + char有冲突,则根据分支数量选取分支数量较少的那个节点做修改,这个状态是从之前空的状态去找空位,因此空洞并不是无限增加的.删除时直接设置那个状态的base和check为0,可供下次插入出现冲突时使用.