Java AC自动机实战:构建高效敏感词过滤系统

AC自动机:如何用多模式串匹配实现敏感词过滤功能 ------ 本文是学习算法的笔记,《数据结构与算法之美》,极客时间的课程 ------ 很多支持用户发表文本内容的网站,比如BBS,大都会有敏感词过滤功能,用来过滤掉用户输入的一些反动谩骂等内容。你有没有想过,这个功能是怎么实现的呢? 实际上,这些功能最基本的原理就是字符串匹配算法,也就是通过维护一个敏感词的字典,当用户输入一段文字内容之后,通过字符串匹配算法,来查找用户输入的这段文字,是否包含... 阅读详情

1. AC自动机算法简介

AC自动机(Aho-Corasick Automaton)是一种高效的多模式字符串匹配算法,由Alfred V. Aho和Margaret J. Corasick于1975年提出。它能在单次扫描文本的同时,检测出所有预定义的模式串(比如敏感词),时间复杂度仅为O(n),与模式串的数量和长度无关。

这个算法特别适合构建敏感词过滤系统,因为它能同时处理成千上万个敏感词,而不会像传统方法那样随着词库增长而性能下降。举个例子,假设我们要过滤"赌博"、"毒品"等敏感词,AC自动机会把这些词构建成一个状态机,检查文本时就像用一把"梳子"快速梳理所有可能性。

2. 核心原理与数据结构

2.1 Trie树基础

AC自动机的核心是基于Trie树(字典树)构建的。Trie树是一种多叉树结构,每个节点代表一个字符,从根节点到某个节点的路径就构成一个字符串前缀。比如敏感词"java"和"python"会共享根节点到"p"节点的路径。

class TrieNode {
    Map<Character, TrieNode> children = new HashMap<>();
    boolean isEnd; // 标记是否为敏感词结尾
    TrieNode fail; // 失败指针
}

2.2 失败指针机制

这是AC自动机的精髓所在。每个节点都有一个fail指针,当匹配失败时,不是从头开始,而是跳转到另一个节点继续匹配。这类似于KMP算法中的next数组,但是扩展到多模式匹配场景。

构建fail指针的过程采用BFS遍历:

  1. 根节点的fail指向自己
  2. 第一层节点fail指向根节点
  3. 其他节点的fail指向父节点fail指针对应字符的子节点

2.3 双数组优化

原始Trie树用Map存储子节点,虽然灵活但性能不够理想。双数组Trie(Double-Array Trie)用两个数组base和check压缩存储结构,可以大幅减少内存占用并提高查询速度。实测表明,这种优化能使性能提升5-9倍。

3. Java实现详解

3.1 引入依赖

推荐使用hankcs开源的AhoCorasickDoubleArrayTrie:

<dependency>
    <groupId>com.hankcs</groupId>
    <artifactId>aho-corasick-double-array-trie</artifactId>
    <version>1.2.3</version>
</dependency>

3.2 构建敏感词库

首先准备敏感词字典,建议使用TreeMap保证有序性:

TreeMap<String, String> sensitiveWords = new TreeMap<>();
sensitiveWords.put("赌博", "赌博");
sensitiveWords.put("毒品", "毒品");
sensitiveWords.put("色情", "色情");

3.3 初始化自动机

AhoCorasickDoubleArrayTrie<String> acdat = new AhoCorasickDoubleArrayTrie<>();
acdat.build(sensitiveWords);

build()方法内部会完成:

  1. 构建基础Trie树
  2. 计算fail指针
  3. 压缩为双数组结构

3.4 文本过滤实战

String text = "这是一个包含赌博和毒品的非法内容";
List<Hit<String>> hits = acdat.parseText(text);
hits.forEach(hit -> System.out.println(
    "发现敏感词[" + hit.value + "] 位置:" + hit.begin + "-" + hit.end
));

输出结果:

发现敏感词[赌博] 位置:6-8
发现敏感词[毒品] 位置:9-11

4. 性能优化技巧

4.1 内存优化

对于中文敏感词,可以使用字符编码优化:

// 将String转为char[]减少内存占用
sensitiveWords.put(new String("赌博".getBytes(), StandardCharsets.UTF_8), "赌博");

4.2 并行构建

当词库超过10万时,可以采用分片并行构建:

List<Map<String, String>> partitions = // 分割词库
partitions.parallelStream().forEach(part -> {
    AhoCorasickDoubleArrayTrie<String> temp = new AhoCorasickDoubleArrayTrie<>();
    temp.build(part);
    // 合并结果
});

4.3 热更新策略

实现动态加载新敏感词:

public class DynamicACAutomaton {
    private volatile AhoCorasickDoubleArrayTrie<String> current;
    
    public void update(Set<String> newWords) {
        TreeMap<String, String> newMap = new TreeMap<>(current.getKeywords());
        newWords.forEach(word -> newMap.put(word, word));
        
        AhoCorasickDoubleArrayTrie<String> newTrie = new AhoCorasickDoubleArrayTrie<>();
        newTrie.build(newMap);
        this.current = newTrie; // 原子切换
    }
}

5. Web应用集成实践

5.1 Spring Boot拦截器

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Autowired
    private SensitiveFilter sensitiveFilter;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HandlerInterceptorAdapter() {
            @Override
            public boolean preHandle(HttpServletRequest request, 
                                   HttpServletResponse response, 
                                   Object handler) throws Exception {
                String content = request.getParameter("content");
                if(sensitiveFilter.containsSensitiveWord(content)) {
                    throw new IllegalRequestException("包含敏感内容");
                }
                return true;
            }
        });
    }
}

5.2 高性能过滤方案

对于高并发场景,建议:

  1. 使用读写锁保证线程安全
  2. 实现多级缓存(本地缓存+Redis)
  3. 采用异步检测机制
public class ConcurrentSensitiveFilter {
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private AhoCorasickDoubleArrayTrie<String> trie;
    
    public boolean containsSensitiveWord(String text) {
        lock.readLock().lock();
        try {
            return !trie.parseText(text).isEmpty();
        } finally {
            lock.readLock().unlock();
        }
    }
    
    public void updateTrie(TreeMap<String, String> newWords) {
        lock.writeLock().lock();
        try {
            AhoCorasickDoubleArrayTrie<String> newTrie = new AhoCorasickDoubleArrayTrie<>();
            newTrie.build(newWords);
            this.trie = newTrie;
        } finally {
            lock.writeLock().unlock();
        }
    }
}

6. 实际应用中的坑与解决方案

6.1 特殊字符处理

遇到用户故意使用变体如"赌⾙"时:

// 统一规范化处理
String normalized = text.replaceAll("[\\uFE00-\\uFE0F]", "")
                      .replaceAll("[\\u200B-\\u200D]", "");

6.2 性能监控

添加指标统计:

public class MonitorableACAutomaton {
    private final AtomicLong counter = new AtomicLong();
    private final AhoCorasickDoubleArrayTrie<String> trie;
    
    public List<Hit<String>> parseText(String text) {
        long start = System.nanoTime();
        List<Hit<String>> result = trie.parseText(text);
        long cost = System.nanoTime() - start;
        counter.addAndGet(cost);
        return result;
    }
    
    public double getAverageCost() {
        return counter.get() / 1_000_000.0; // 转为毫秒
    }
}

6.3 词库维护建议

  1. 按业务领域分组词库(政治、色情、广告等)
  2. 建立词权重机制
  3. 定期审核误杀案例
  4. 实现AB测试验证新词效果

我在实际项目中遇到过词库过大导致初始化慢的问题,后来通过分级加载(先加载高频词,异步加载全量词库)解决了冷启动延迟。另外建议对匹配结果做上下文分析,避免误伤正常用语。

【实战场景】敏感词过滤如何实现? 首先,需要一个包含所有需要过滤的敏感词的列表或数据库。这个列表可以手动创建,也可以从现有的资源中导入。敏感词库应该定期更新以反映新的敏感词汇。 阅读详情

相关推荐

KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤敏感词

KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤敏感词

架构师尼恩 985

AC自动机(java)

AC自动机算法是一种基于Trie树和有限状态机的字符串匹配算法。它在查找字符串时,利用额外的失配指针进行回退,转向其他分支,避免重复匹配前缀,从而提高算法效率。当一个字典串集合是已知的,AC自动机算法可以以离线方式先求出并储存自动机,以便日后使用。在这种情况下,算法的时间复杂度为输入字符串长度和匹配数量之和。AC自动机算法的主要优势是高效、快速,能够在大量文本中快速查找匹配项。AC自动机算法的流程包括以下几个步骤:1.构建Trie树:将所有字典串集合中的串进行前缀压缩,得到Trie树。

SP_1024的博客 719

亿级流量敏感词过滤系统设计(支持敏感词毫秒级生效)

本文设计的亿级流量敏感词过滤系统,核心是“算法优化+分布式架构+动态更新”的三位一体:通过AC-DAT算法保障匹配效率,通过分布式集群保障高吞吐高可用,通过“配置中心推送+双缓冲加载”实现敏感词毫秒级生效。基于Java生态技术栈,方案具备良好的可落地性和扩展性。AI辅助过滤:结合NLP模型识别变体敏感词(如谐音、形近字、拼音混合,如“色qíng”),弥补传统字符串匹配的不足;边缘计算部署:将过滤服务部署在边缘节点,降低跨地域请求的网络延迟;灰度发布。

u013127325的博客 1023

AC自动机-Java

AC算法

xuanzui的博客 1405

ac自动机java版

从别的共享资源下载的java版ac自动机,已验证使用非常好。

AC算法(java实现)

AC算法的java版实现(原创),仅供初学者参考,不得用于其他用途

AC自动机算法详解以及Java代码实现

详细介绍了AC自动机算法详解以及Java代码实现。

终生学习践行者 3507

java编程之AC自动机工作原理与实现代码

主要介绍了java编程之AC自动机的有关内容,涉及其应用场景,运行原理,运行过程,构造方法及Java中的实现代码,具有一定参考价值,需要的朋友可以了解下。

字符串匹配与文本处理(七):AC自动机

本文深入解析了AC自动机(Aho-Corasick Automaton)这一高效的多模式字符串匹配算法。文章首先介绍了AC自动机的核心概念,包括字典树(Trie)和失败指针的实现原理。随后详细阐述了其工作原理,分为预处理阶段(构建字典树和失败指针)和匹配阶段,并分析了O(n)的时间复杂度优势。通过完整的Java代码实现,展示了如何定义字典树节点、构建失败指针以及执行文本匹配。最后,将AC自动机与其他字符串匹配算法(KMP、Boyer-Moore等)进行对比,突出其在多模式匹配场景中的高效性。本文为理解AC自

一碗黄焖鸡三碗米饭的博客 891

Java实现AC自动机全文检索示例

本篇文章主要介绍了Java实现AC自动机全文检索示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

解决Surface更新后Bitlocker无限循环的问题

在Surface系统更新以后,出现要求输入Bitlocker恢复密钥的问题。已经输入正确密钥以后,依然无法正常进入Windows操作系统,一旦重启依然循环Bitlocker要求输入密钥的界面。 一旦到登录界面,点击“登录”之后又跳转回登录界面.,但就是无法进入桌面。 解决方案: 拒绝暴力重装!这个问题是Bitlock把盘给锁了,所以要解锁 重启之后,直接点击右下角“跳过这个驱动器” 选择“疑难解答”,然后进入命令提示符 先查看判断现在是不是被锁了: 输入: manage-bde -status c

premierapp的博客 1万+

AC自动机详解:高效多模式字符串匹配

AC自动机(Aho-Corasick算法)是一种用于多模式字符串匹配的高效算法,广泛应用于敏感词过滤、文本搜索等领域。本文将深入探讨AC自动机的工作原理、构建过程以及如何使用Java语言来实现这一强大的算法。

xiaoyu❅的博客 2338

STM32G4系列数字LLC控制程序开发实战

本文详细介绍了基于STM32G4系列MCU的数字LLC控制程序开发全流程。从开发环境搭建、中断服务函数设计,到核心的电压环PID算法、Burst模式控制、状态机设计以及软启动优化,提供了完整的实战代码和关键参数调试经验,帮助开发者高效实现高性能数字电源控制。

weixin_29185493的博客 278

AC自动机算法原理详解与敏感词过滤实现(JAVA保姆级详解)

JAVA浅显易懂的AC自动机详解,用于实现敏感词过滤

qq_74851649的博客 2744

基准电压 + 运放 + 低边MOS恒流源控制原理

因为恒流源强制 Iout不变,而 Vin​ 增加时,负载压降 Iout⋅Rload不变,多余的电压只能由MOS管的 VDS承担,因此 VDS必然增加。在饱和区,MOS 管的 ID 仅由 VGS决定,与 VDS 无关,这样,负载变化时,VDS可自由调整以维持 Iout恒定。当 Vin​ 小到无法满足 VDS>VGS−Vth时,MOS管进入线性区,Iout 会随 Vin​ 下降而减小,恒流失效。由于 Vref和 Rsense未变,Iout无需调整,运放无需动作,OUT保持不变,Iout恒定。

weixin_50643237的博客 2652

HWSD全球土壤数据下载、处理与提取完整指南

全球尺度的科学研究与工程项目中,土壤数据是必不可少的基础底图,而HWSD(和谐世界土壤数据库)凭借其统一的分辨率与属性标准,成为农业区划、生态模型、土地利用变化和水资源评估等领域的通用数据源。深入理解其“栅格存编号、数据库存属性”的核心原理,是高效使用这套数据的关键。通过掌握MDB数据库结构、属性字段含义以及栅格与属性表的关联方法,研究者可以将原始数据转化为可用的研究底图。无论你是需要提取特定区域的土壤属性,还是进行面积统计与点位采样,合理的处理流程都能显著提升工作效率。本文从下载注册开始,一步步梳理数据清

weixin_29056781的博客 313

敏感词过滤系统设计,基于Java的DFA与AC自动机实现深度对比

解决敏感词高效过滤难题,基于Java实现DFA与AC自动机的深度对比,涵盖文本审核、聊天内容过滤等场景。分析两种算法在性能、内存占用与扩展性上的优劣,提供完整实现思路与优化建议。Java敏感词过滤实现方案详解,值得收藏。

QuickProceed的博客 1107

别再死记硬背参数了!用ADS手把手教你仿真一个4GHz镜像抑制混频器(附完整工程文件)

本文详细解析了4GHz镜像抑制混频器的ADS仿真全流程,从理论到实践,涵盖混频器设计基础、ADS工程搭建、二极管选型、非线性仿真及性能优化。通过实战案例,帮助工程师掌握关键参数平衡与调试技巧,提升射频电路设计效率。

weixin_42552716的博客 338

Java怎么实现一个敏感词过滤?有哪些方法?怎么优化?

,"stopwords": ["敏感词1", "敏感词2", "违法词"]},"type": "keyword" // 保留原始内容。

gwndjsh的博客 4213

LeRobot 入门教程(十一)π0(Pi0)π0.5(Pi0.5)训练、推理、部署

本文介绍了Physical Intelligence公司开发的π₀和π₀.₅系列通用机器人控制视觉-语言-动作模型。π₀作为首款基础模型,融合流匹配、跨实体训练等技术,支持50Hz高频控制。π₀.₅是其升级版,通过异构数据协同训练解决开放世界泛化问题,在Libero基准测试中表现优异。文章详细说明了两个模型的安装要求、使用方法、训练策略及关键参数配置,包括混合精度训练、梯度检查点等优化技术,为机器人在多样化场景中的语义理解和动作控制提供了完整解决方案。

2506_90492529的博客 5036

Tmux学习总结

Tmux 重要概念 使用 Tmux 的时候千万不要去背指令,所有的指令都可以在 .tmux.conf 配置文件中绑定自己顺手的快捷键,也可以配置开启鼠标。 这个是我的配置文件:https://github.com/zuorn/tmux.conf 在Tmux逻辑中,需要分清楚Server > Session > Window > Pane这个大小和层级顺序是极其重要的,直接关系到工作效率: Server:是整个tmux的后台服务。有时候更改配置不生效,就要使用tmux kill-

满目星辰 577

Java Aho-Corasick 自动机在敏感词过滤中的高效应用

本文深入探讨了Aho-Corasick自动机在Java敏感词过滤中的高效应用。通过对比暴力匹配,详细解析了AC自动机结合Trie树与KMP算法的核心原理,并提供了完整的Java实现代码。文章进一步介绍了双数组Trie等性能优化方案,以及如何在高并发场景(如Netty框架)中集成,旨在帮助开发者构建高性能、可扩展的敏感词过滤系统。

v6b7n8m9q0的博客 783

Simulink中搭建一个包含PID控制的压电陶瓷快反镜模型

这个模型只是一个基本框架,你需要根据实际的系统参数和要求进行调整和优化。希望这些步骤能帮助你在Simulink中搭建所需的模型。

AI的内部世界的博客 474

【Java敏感词过滤实战指南】:掌握高效过滤算法与企业级应用技巧

掌握Java敏感词过滤实现方法,有效解决内容安全难题。适用于评论审核、聊天过滤等场景,基于DFA算法实现高性能匹配,支持动态更新敏感词库。提供完整代码示例与优化技巧,企业级应用实践值得收藏。

StepNexus的博客 789

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

敏感词算法

首先,需要一个包含所有需要过滤的敏感词的列表或数据库。这个列表可以手动创建,也可以从现有的资源中导入。敏感词库应该定期更新以反映新的敏感词汇。

00 后码农一枚,痴迷代码,以键为剑,以思为芒。于 优快云 镌刻编程成长,愿与诸君共探技术星河,同铸数字梦想。 2054

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

java 敏感词多模过滤_AC自动机-去除敏感字符

AC自动机AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一。一个常见的例子就是打游戏聊天时,你说的一些铭感词会变成‘*’。要搞懂AC自动机,先得有模式树(字典树)Trie和KMP模式匹配算法的基础知识。KMP算法是单模式串的字符匹配算法,AC自动机是多模式串的字符匹配算法。基于单模式串和Trie树实现的敏感词过滤字符串匹配算法...

weixin_35648264的博客 597
上一篇: FTP匿名登录的隐藏风险:从VSFTPD漏洞看企业文件服务器的5大安全盲区
下一篇: 超效率SBM模型实战:从理论到案例解析
sql99
博客等级 码龄19年 168粉丝 1905原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值