使用 Java 实现基于 DFA 算法的敏感词检测

使用 Java 实现基于 DFA 算法的敏感词检测

1. 引言

敏感词检测在内容审核、信息过滤等领域有着广泛的应用。本文将介绍如何使用 DFA(Deterministic Finite Automaton,确定有限状态自动机) 算法,在 Java 中实现高效的敏感词检测。

2. DFA 算法简介

DFA(确定有限状态自动机)是一种用于字符串匹配的高效算法。它的核心思想是将多个敏感词组织成一棵状态机,在匹配过程中避免重复扫描,提升检测速度。

DFA 的构建分为两个阶段:

  1. 构建状态机(即DFA树):将敏感词列表逐字构建成一个树形结构,每个字符对应一个节点,单词的结束位置标记为终止状态。
  2. 文本匹配:使用状态机遍历输入文本,遇到匹配字符时进入下一个状态,直到匹配完整的敏感词。
    DFA树

DFA 的优点在于匹配时的时间复杂度是 O(n),即文本长度的线性时间,适用于高性能需求的敏感词检测。

3. Java 实现 DFA 敏感词检测
3.1 定义 DFA 结构
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class SensitiveWordNode {
    private boolean isEnd;
    private Map<Character, SensitiveWordNode> children;

    public SensitiveWordNode() {
        this.isEnd = false;
        this.children = new HashMap<>();
    }

    public void addChild(Character c) {
        children.putIfAbsent(c, new SensitiveWordNode());
    }

    public SensitiveWordNode getChild(Character c) {
        return children.get(c);
    }

    public boolean isEnd() {
        return isEnd;
    }

    public void setEnd(boolean end) {
        isEnd = end;
    }
}
3.2 构建 DFA 敏感词树
public class SensitiveWordDFA {
    private SensitiveWordNode root;
    
    public SensitiveWordDFA(Set<String> sensitiveWords) {
        root = new SensitiveWordNode();
        for (String word : sensitiveWords) {
            insertWord(word);
        }
    }
    
    private void insertWord(String word) {
        SensitiveWordNode node = root;
        for (char c : word.toCharArray()) {
            node.addChild(c);
            node = node.getChild(c);
        }
        node.setEnd(true);
    }
    
    // 最小检测模式(检测到一个敏感词就返回)
    public boolean containsSensitiveWord(String text) {
        for (int i = 0; i < text.length(); i++) {
            SensitiveWordNode node = root;
            for (int j = i; j < text.length(); j++) {
                node = node.getChild(text.charAt(j));
                if (node == null) {
                    break;
                }
                if (node.isEnd()) {
                    return true;
                }
            }
        }
        return false;
    }
    
    // 最大检测模式(返回所有匹配的敏感词)
    public Set<String> findAllSensitiveWords(String text) {
        Set<String> result = new HashSet<>();
        for (int i = 0; i < text.length(); i++) {
            SensitiveWordNode node = root;
            StringBuilder wordBuffer = new StringBuilder();
            for (int j = i; j < text.length(); j++) {
                node = node.getChild(text.charAt(j));
                if (node == null) {
                    break;
                }
                wordBuffer.append(text.charAt(j));
                if (node.isEnd()) {
                    result.add(wordBuffer.toString());
                }
            }
        }
        return result;
    }
}
3.3 测试 DFA
import java.util.HashSet;
import java.util.Set;

public class SensitiveWordTest {
    public static void main(String[] args) {
        Set<String> sensitiveWords = new HashSet<>();
        sensitiveWords.add("敏感");
        sensitiveWords.add("违规");

        SensitiveWordDFA dfa = new SensitiveWordDFA(sensitiveWords);
        
        String text1 = "这是一条包含敏感内容的文本";
        String text2 = "这是一条正常文本";
        
        System.out.println("文本1是否包含敏感词: " + dfa.containsSensitiveWord(text1));
        System.out.println("文本2是否包含敏感词: " + dfa.containsSensitiveWord(text2));
        
        String text3 = "这条信息涉及违规行为和敏感内容";
        System.out.println("文本3包含的敏感词: " + dfa.findAllSensitiveWords(text3));
    }
}
4. 优化方向
  • 支持动态添加敏感词,避免重新构建 DFA。
  • 增加敏感词替换功能,将匹配到的敏感词替换为 * 或其他符号。
  • 使用 AC 自动机,进一步提高匹配效率。
5. 结论

本文介绍了 DFA(确定有限状态自动机) 的基本原理,并使用 Java 进行了敏感词检测的实现。DFA 具备 高效、可扩展 的特点,适用于大规模敏感词匹配场景。希望对你有所帮助!

阅读原文

原文连接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/955838.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

单片机存储器和C程序编译过程

1、 单片机存储器 只读存储器不是并列关系&#xff0c;是从ROM发展到FLASH的过程 RAM ROM 随机存储器 只读存储器 CPU直接存储和访问 只读可访问不可写 临时存数据&#xff0c;存的是CPU正在使用的数据 永久存数据&#xff0c;存的是操作系统启动程序或指令 断电易失 …

UDP报文格式

UDP是传输层的一个重要协议&#xff0c;他的特性有面向数据报、无连接、不可靠传输、全双工。 下面是UDP报文格式&#xff1a; 1&#xff0c;报头 UDP的报头长度位8个字节&#xff0c;包含源端口、目的端口、长度和校验和&#xff0c;其中每个属性均为两个字节。报头格式为二…

2024年我的技术成长之路

2024年我的技术成长之路 大家好&#xff0c;我是小寒。又到年底了&#xff0c;一年过得真快啊&#xff01;趁着这次活动的机会&#xff0c;和大家聊聊我这一年在技术上的收获和踩过的坑。 说实话&#xff0c;今年工作特别忙&#xff0c;写博客的时间比去年少了不少。不过还是…

HTML5+Canvas实现的鼠标跟随自定义发光线条源码

源码介绍 HTML5Canvas实现的鼠标跟随自定义发光线条特效源码非常炫酷&#xff0c;在黑色的背景中&#xff0c;鼠标滑过即产生彩色变换的发光线条效果&#xff0c;且线条周围散发出火花飞射四溅的粒子光点特效。 效果预览 源码如下 <!DOCTYPE html PUBLIC "-//W3C//D…

爬虫第二篇

太聪明了怎么办&#xff1f;那就&#xff0c;给脑子灌点水&#xff01;&#xff01; 本篇文章我们来简单讲一下如何爬取mv,也就是歌曲视频&#xff0c;那么我们进入正题。 由于上次拿网易云开了刀&#xff0c;那么这次我们拿酷狗开刀。 还是进入上次讲过的页面 注意&#xff…

C#表达式和运算符

本文我们将学习C#的两个重要知识点&#xff1a;表达式和运算符。本章内容会理论性稍微强些&#xff0c;我们会尽量多举例进行说明。建议大家边阅读边思考&#xff0c;如果还能边实践就更好了。 1. 表达式 说到表达式&#xff0c;大家可能感觉有些陌生&#xff0c;我们先来举个…

Jira中bug的流转流程

Jira中bug的状态 1. 处理Bug的流程2. bug状态流转详述bug的状态通常包括 1. 处理Bug的流程 2. bug状态流转详述 bug的状态通常包括 未解决 1. 测试人员创建一个bug&#xff0c;填写bug的详细信息&#xff0c;如概要、bug级别、复现步骤、现状、预期结果等 2. 定位bug&#x…

快手极速版如何查找ip归属地?怎么关掉

在数字化时代&#xff0c;个人隐私的保护成为了广大用户关注的焦点。快手极速版作为一款备受欢迎的短视频应用&#xff0c;其IP归属地的显示与关闭功能自然也成了用户热议的话题。本文将详细介绍如何在快手极速版中查找IP归属地以及如何关闭IP属地显示&#xff0c;帮助用户更好…

BGP边界网关协议(Border Gateway Protocol)路由引入、路由反射器

一、路由引入背景 BGP协议本身不发现路由&#xff0c;因此需要将其他协议路由&#xff08;如IGP路由等&#xff09;引入到BGP路由表中&#xff0c;从而将这些路由在AS之内和AS之间传播。 BGP协议支持通过以下两种方式引入路由&#xff1a; Import方式&#xff1a;按协议类型将…

Solidity03 Solidity变量简述

文章目录 一、变量简述1.1 状态变量1.2 局部变量1.3 全局变量1.4 注意问题 二、变量可见性2.1 public2.2 private2.3 internal2.4 默认可见性2.5 可见性的用处 三、变量初始值3.1 值类型初始值 一、变量简述 变量是指可以保存数据的内部存储单元&#xff0c;里面的数据可以在程…

数据结构---并查集

目录 一、并查集的概念 二、并查集的实现 三、并查集的应用 一、并查集的概念 在一些实际问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元素集合&#xff0c;然后按一定的规律将归于同一组元素的集合…

STM32 FreeRTOS内存管理简介

在使用 FreeRTOS 创建任务、队列、信号量等对象时&#xff0c;通常都有动态创建和静态创建的方式。动态方式提供了更灵活的内存管理&#xff0c;而静态方式则更注重内存的静态分配和控制。 如果是1的&#xff0c;那么标准 C 库 malloc() 和 free() 函数有时可用于此目的&#…

构建core模块

文章目录 1.环境搭建1.sunrays-common下新建core模块2.引入依赖&#xff0c;并设置打包常规配置 2.测试使用1.启动&#xff01;1.创建模块2.引入依赖3.application.yml 配置MySQL和Minio4.创建启动类5.启动测试 2.common-web-starter1.目录2.WebController.java3.结果 3.common…

【Flink系列】6. Flink中的时间和窗口

6. Flink中的时间和窗口 在批处理统计中&#xff0c;我们可以等待一批数据都到齐后&#xff0c;统一处理。但是在实时处理统计中&#xff0c;我们是来一条就得处理一条&#xff0c;那么我们怎么统计最近一段时间内的数据呢&#xff1f;引入“窗口”。 所谓的“窗口”&#xff…

AIGC与劳动力市场:技术进步与就业结构的重塑

随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;尤其是生成式AI&#xff08;AIGC&#xff09;&#xff0c;劳动力市场正经历前所未有的变革。从内容创作到自动化生产线&#xff0c;几乎每个行业都在经历一场技术的洗礼。然而&#xff0c;这场革命并不是全然…

废品回收小程序,数字化回收时代

随着科技的不断创新发展&#xff0c;废品回收在各种技术的支持下也在不断地创新&#xff0c;提高了市场的发展速度&#xff0c;不仅能够让回收效率更加高效&#xff0c;还能够让居民更加便捷地进行回收&#xff0c;推动废品回收行业的发展。 回收市场机遇 目前&#xff0c;废…

题解 CodeForces 430B Balls Game 栈 C/C++

题目传送门&#xff1a; Problem - B - Codeforceshttps://mirror.codeforces.com/contest/430/problem/B翻译&#xff1a; Iahub正在为国际信息学奥林匹克竞赛&#xff08;IOI&#xff09;做准备。有什么比玩一个类似祖玛的游戏更好的训练方法呢&#xff1f; 一排中有n个球…

【Linux】线程全解:概念、操作、互斥与同步机制、线程池实现

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长&#xff0c;行则将至 目录 &#x1f4da;一、线程概念 &#x1f4d6; 回顾进程 &#x1f4d6; 引入线程 &#x1f4d6; 总结 &a…

PDF文件提取开源工具调研总结

概述 PDF是一种日常工作中广泛使用的跨平台文档格式&#xff0c;常常包含丰富的内容&#xff1a;包括文本、图表、表格、公式、图像。在现代信息处理工作流中发挥了重要的作用&#xff0c;尤其是RAG项目中&#xff0c;通过将非结构化数据转化为结构化和可访问的信息&#xff0…

简历_使用优化的Redis自增ID策略生成分布式环境下全局唯一ID,用于用户上传数据的命名以及多种ID的生成

系列博客目录 文章目录 系列博客目录WhyRedis自增ID策略 Why 我们需要设置全局唯一ID。原因&#xff1a;当用户抢购时&#xff0c;就会生成订单并保存到tb_voucher_order这张表中&#xff0c;而订单表如果使用数据库自增ID就存在一些问题。 问题&#xff1a;id的规律性太明显、…