字典树/数据结构/加速字符串查询

字典树(Trie)

试想一个经典的场景:

​ 有一个字符串集合 C = [s1, s2, …, sn],给定字符串 t,要判断 t是否在集合 C中

解法一

利用遍历的思想,逐个遍历字符串数组:

#C = [s1, s2, ..., sn]
#t = 'xxx.xxx'
def find(C, t):
  for s in C:
    if t == s:
      return True
  return False

假设字符串的平均长度为m,t的长度为k,C中有n个元素,这样做的时间复杂度为 O ( m i n ( m , k ) ∗ n ) = O ( n m ) O(min(m, k)*n) = O(nm) O(min(m,k)n)=O(nm).

如果我们想达到更低的时间复杂度,就需要利用到字典树.

解法二:字典树

首先需要回答的是:什么是字典树?

字典树: 利用字符串的前缀来构建的一棵保存若干个字符串信息的树

image-20201106101802082

从根节点到叶节点的路径上的边构成了一个完成的字符串,例如路径:0->1->2->3,表示字符串:“inn”.

字典树的构建

字典树的构建关键在于构建一条路径,使得从根节点到叶节点的路径代表着字符串本身。由于是从根节点开始往下,考虑相同前缀的情况:例如"int"和"inn"就有着相同的前缀,那么无需重新添加新的结点,直接共用结点0,1,2即可.

由此我们得出了构建字典树的算法:

  1. 建立字典树的根结点 0,每个字符串都将从 0开始往下搜索
  2. 从集合 C中取一个字符串 s,设置树的遍历指针 p为根结点 0
  3. 在字符串 s中取一个字符 c,如果指针 p指向的结点存在一条边的值为 c,那么把p指向这条边所指向的结点,重复过程3;否则,生成新的值为 c的边 e,并添加一个新的结点 v,让 e指向 v,p指向新的结点v. 直到取完完字符串s
  4. 重复过程2直到集合 C中元素被取完

为了更好的理解上述算法过程,我们举一个栗子(例子!).

例1:字符串集合 C = [‘inn’, ‘int’],要构建一颗字典树.

  1. 创建根结点0
image-20201106101802082
  1. 建立’inn’的路径
  2. 建立’int’的路径
image-20201106104953137

Talk is cheap. Show me your code

下面给出构建字典树的python版本.

from typing import List

alphabet_size = 200
max_str_size = 1000
    
def build_dict_tree(words: List[str]) -> List[List[int]]:
  dict_tree = [[-1] * alphabet_size for _ in range(max_str_size)]
  node_num = 1
  for word in words:
    p = 0
    for c in word:
      c = ord(c)
      assert(0 <= c < alphabet_size)
      if dict_tree[p]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值