字典树的实际应用场景之敏感词过滤(附 Java 实现代码)

本文详细介绍了如何使用字典树(Trie)进行敏感词过滤,对比了不同匹配算法的时间复杂度,并提供了Java代码实现。通过建立敏感词库构建字典树,遍历文本实现高效过滤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

这篇文章主要介绍怎么用字典树实现敏感词的过滤,关于字典树的一些介绍可以参考其他文章,也看一下我的另一篇文章:Trie(字典树,前缀树)及其实现

敏感词过滤

在很多场景都会用到敏感词过滤,比如在网站提交的内容,游戏中的聊天等等…那么这些敏感词是如何被过滤掉的呢?其实这就是一个字符串的匹配过程,我们很容易就可以想到的就是准备一个敏感词库,然后用每一个敏感词去要过滤的文本中匹配,匹配成功则用 *** 来代替敏感词,不同的匹配算法的时间复杂度是不一样的,比如敏感词的长度为m,待过滤文本的长度为 n,有如下几种匹配算法:

  • 暴力破解法,利用两层循环来实现,时间复杂度为O(m * n);
  • KMP算法:时间复杂度为 O(n + m);
  • 字典树:时间复杂度为O(n);
Trie 实现敏感词的过滤

关于 KMP 算法的实现可以参考其他文章或者我的另外两篇文章:字符串模式匹配算法的 Java 实现关于 KMP 算法的个人理解(附 Java 实现代码)

首先,在进行敏感词过滤之前我们需要有一个敏感词库,用这个敏感词库来建立字典树,比如我们现在有两个敏感词:“de”, “bca”,建立字典树,根节点不存放任何东西,其他每个子节点存放一个字符,深红色代表单词结尾,如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190713205451638.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxOTAwMDgx,size_16,color_FFFFFF,t_70#pic_center
建立完字典树之后,我们就要利用这棵由敏感词组成的字典树匹配字符串了。

现在,我们有一段文本 “abcadef" ,目的是将其中的 “de”, “bca”,过滤掉,具体算法如下:

  • 为了遍历字符串和字典树,我们假设有三个指针,p1,p2,p3,其中p1指向字典树根节点,p2 和 p3 指向字符串的第一个字符,如下:

在这里插入图片描述

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

在这里插入图片描述

  • 然后从字符串 b 开始查找,看看是否有以 b 作为前缀的字符串,p1 的孩子节点中有 b,这时,我们把 p1 指向节点 b,由于此时 b 不是单词的结尾,所以p3 向右移动一格,不过,p2 不动。
    在这里插入图片描述
  • 判断 p1 的孩子节点中是否存在 p3 指向的字符 c,显然有。我们把 p1 指向节点 c,p3 向右移动一格,p2 不动。
    在这里插入图片描述
  • 判断 p1 的孩子节点中是否存在 p3 指向的字符 a,显然有,且 a 是字符串 “bca” 的结尾。这意味着,p2 到 p3之间为敏感词 “bca”,把 p2 和 p3 指向的区间那些字符替换成 *。这时我们把 p2 和 p3 都移向字符 d,p1 还是还原到最开始指向 root。

在这里插入图片描述

  • 和前面的步骤一样,判断有没以 d 作为前缀的字符串,显然这里有 “de”,所以把 p2 和 p3 移到字符 f。

在这里插入图片描述

  • 因为根节点没有子节点 f,所以匹配结束。

在 Java 中可以利用 HashMap 来存放一层树结点,则每个敏感词的查找时间复杂度是 O (1),字符串的长度为 n,我们需要遍历 1 遍,所以敏感词查找这个过程的时间复杂度是 O (n * 1)。如果每个敏感词的平均长度为 m,有 t 个敏感词的话,构建 trie 树的时间复杂度是 O (t * m)。

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

Java 代码实现
import org.apache.commons.lang.CharUtils;
import java.util.HashMap;
import java.util.Map;

public class MyTrie {
   
    private class TrieNode {
   
        /**
         * 是否敏感词的结尾
         */
        private boolean isEnd = false;

        /**
         * 下一层节点
         */
        Map<Character, TrieNode>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值