敏感词过滤--trie树

本文介绍了如何使用Trie树进行敏感词过滤。在面试中,小秋解释了Trie树的构造,利用其共享公共前缀的特性节省空间。通过遍历文本和Trie树,可以检测并替换敏感词。文章还分析了时间复杂度,并讨论了在PHP中使用HashMap实现Trie树的可能性。
摘要由CSDN通过智能技术生成
定义

trie 树也称为字典树、单词查找树,最大的特点就是共享字符串的公共前缀来达到节省空间的目的了。例如,字符串 "abc"和"abd"构成的 trie 树如下:

在这里插入图片描述
trie 树的根节点不存任何数据,每整个个分支代表一个完整的字符串。像 abc 和 abd 有公共前缀 ab,所以我们可以共享节点 ab。如果再插入 abf,则变成这样:
在这里插入图片描述

如果我再插入 bc,则是这样(bc 和其他三个字符串没有公共前缀)

在这里插入图片描述

面试官:那如果再插入 “ab” 这个字符串呢?

小秋:差点说了,每个分支的内部可能也含有完整的字符串,所以我们可以对于那些是某个字符串结尾的节点做一个标记,例如 abc, abd,abf 都包含了字符串 ab,所以我们可以在节点 b 这里做一个标记。如下(我用红色作为标记):
在这里插入图片描述

面试官:可以说说 trie 树有哪些应用吗?

小秋:trie 最大的特点就是利用了字符串的公共前缀,像我们有时候在百度、谷歌输入某个关键字的时候,它会给我们列举出很多相关的信息
在这里插入图片描述

这种就是通过 trie 树来实现的。

小秋:(嗯? trie 又称为单词查找树,好像可以用 trie 来实现刚才的敏感词匹配?面试官无缘无故提 trie 树难道别有用意?)

面试官:刚才的敏感词过滤,其实也可以采用 trie 来实现,你知道怎么实现吗?

trie 树来实现敏感词过滤

小秋:(果然,面试官真是个好人啊,直接提示了,要是还不知道怎么实现,那不真凉?)我想想………我知道了,我可以这样来实现:

先把你给我的三个敏感词:“de”, “bca”, “bcf” 建立一颗 trie 树,如下:

接着我们可以采用三个指针来遍历,我直接用上面你给你例子来演示吧。

1、首先指针 p1 指向 root,指针 p2 和 p3 指向字符串第一个字符
在这里插入图片描述

2、然后从字符串的 a 开始,检测有没有以 a 作为前缀的敏感词,直接判断 p1 的孩子节点中是否有 a 这个节点就可以了,显然这里没有。接着把指针 p2 和 p3 向右移动一格。
在这里插入图片描述

3、然后从字符串 b 开始查找,看看是否有以 b 作为前缀的字符串,p1 的孩子节点中有 b,这时,我们把 p1 指向节点 b,p2 向右移动一格,不过,p3不动。
在这里插入图片描述

4、判断 p1 的孩子节点中是否存在 p2 指向的字符c,显然有。我们把 p1 指向节点 c,p2 向右移动一格,p3不动。
在这里插入图片描述

5、判断 p1 的孩子节点中是否存在 p2 指向的字符d,这里没有。这意味着,不存在以字符b作为前缀的敏感词。这时我们把p2和p3都移向字符c,p1 还是还原到最开始指向 root。
在这里插入图片描述

6、和前面的步骤一样,判断有没以 c 作为前缀的字符串,显然这里没有,所以把 p2 和 p3 移到字符 d。
在这里插入图片描述

7、然后从字符串 d 开始查找,看看是否有以 d 作为前缀的字符串,p1 的孩子节点中有 d,这时,我们把 p1 指向节点 b,p2 向右移动一格,不过,p3和刚才一样不动。(看到这里,我猜你已经懂了)
在这里插入图片描述

8、判断 p1 的孩子节点中是否存在 p2 指向的字符e,显然有。我们把 p1 指向节点 e,并且,这里e是最后一个节点了,查找结束,所以存在敏感词de,即 p3 和 p2 这个区间指向的就是敏感词了,把 p2 和 p3 指向的区间那些字符替换成 *。并且把 p2 和 p3 移向字符 f。如下:
在这里插入图片描述

9、接着还是重复同样的步骤,知道 p3 指向最后一个字符。

复杂度分析

面试官:可以说说时间复杂度吗?

小秋:如果敏感词的长度为 m,则每个敏感词的查找时间复杂度是 O(m),字符串的长度为 n,我们需要遍历 n 遍,所以敏感词查找这个过程的时间复杂度是 O(n * m)。如果有 t 个敏感词的话,构建 trie 树的时间复杂度是 O(t * m)。

这里我说明一下,在实际的应用中,构建 trie 树的时间复杂度我觉得可以忽略,因为 trie 树我们可以在一开始就构建了,以后可以无数次重复利用的了。

如果让你来 构建 trie 树,你会用什么数据结构来实现?

小秋:我一般使用 Java,我会采用 HashMap 来实现,因为一个节点的字节点个数未知,采用 HashMap 可以动态拓展,而且可以在 O(1) 复杂度内判断某个子节点是否存在。

实现

安装PHP扩展 trie_filter

1、敏感词库维护更新脚本:

reload_dict.php,提供自动更新字典库到trie-tree文件的过程

<?php

// 设置内存
ini_set('memory_limit', '128M');

// 读取敏感词字典库
$handle = fopen
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值