双数组trie

1.概念: 双数组的本质实际上就是一个有限状态的自动机。它能根据输入的字符转移到下一状态,最终到达终止状态。
2.用处:能够用o(n)的时间复杂度进行字符串识别,缺点是占用较多的内存,存储数组是一个稀疏数组。
2.双数组示意图

                           双数组trie的实现
                                                                  图一:双数组示意图
实例图说明:方框表示接受方框中的字符后到达的状态,椭圆表示终止状态。
可识别的字符串包括:北大荒,北大荒蜂蜜,北郊,程序员,潘丽芳程序员,潘丽芳

双数组使用两个数组表示:base数组,check数组,

双数组trie的实现
如果状态s接受字符c输入转化到状态t,这双数组必须满足
next[base[s]+c] = t;
check[base[s]+c] = s

上面的示意图用base,check数组存储得到下面的数组示意图
base_index: 0      1      7       10      15       16      17      19      20    21       22      24    25    27   28    33 base_con:            13    19      13       13      -16    -17    -19    25    13      -22      13   -13    13   -28   19
check_con:          0      0         0       1         15      1       21      25    16       27      10    24    7    33   20
字符串                北    程      潘    北大    北大荒 北郊 北大荒蜂蜜   北大荒蜂程序员潘丽潘丽芳 程序

北:1    大:2      荒:3   郊:4   蜂:5    蜜:6    程:7   序:8    员:9   潘:10 丽:11   芳:12

因为有12个不同的字符,所有我选取base[s] = 13;
北大荒的构造过程:北的index=1,并且base[s] = 13;所以base[1] = 13,check[1] = 0(北的前面是初始状态)
大的index=2.所以base[base[1]+2]=15,所以base[15]=13,check[15]=1(大的前面是北所在的index),
荒的index=3,所以base[base[15]+3]=16,所以base[16]=13,check[16]=15,但是由于‘荒’就一个结束状态。所以base[16] = -1*base[16];便于识别结束状态
程序员的构造过程:程的index=7,base[7]=13,check[7]=0;
序的index=8,base[base[7]+8]=21,base[21]!=0发生碰撞,调整base[s] = 13+6=19,所有base[7]=19,base[base[7]+8]=27, base[27]=13 check[27]=7,
员的index=9,base[base[27]+9]=22,员是结束状态,所以base[22]=-22,check[22]=27
几点感想:
base[s]的选举:根据自己的需要灵活选取,过大可能会造成base数组过于稀疏,过小可能会造成碰撞较多。
碰撞:指执行next[base[s]+c] = t后,base[base[s]+c]不为空,这是需要重新选取base[s],我选取的base[s] = base[s] +6
当发生碰撞时,要选择合适的base[s]使得以这个状态为当前状态的所有下一状态都能找到base中的空位子。比如北大荒,北郊,当输入'郊'以后到达的位置如果遇到碰撞,重新选取base[s],需要保证在新的base[i]下输入'大'到达的位置也为空。在最开始选择base[s]无法知道是否会产生碰撞,只有在发生碰撞时调整base[s],保证所有的输入c,base[base[s]+c]都为空。
base[i] < 0:比如“荒”是结束状态,但它同时是北大荒蜂蜜的中间状态,在寻找下一个位置时base[s] = 0-base[s]
北大荒和北大荒蜂蜜同时出现时,北大荒蜂蜜首先被识别。
我所实现的数据结构将词条插入看做词条增加。
实现的数据结构和可能有多种,对应有相应的算法,但算法思想大致如上。
按照构造算法即可推出查询算法。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值