敏感词匹配DFA算法

算法简介与场景介绍

DFA算法,中文全称为确定性有穷自动机。它的基本思想是构建一个有穷自动机,当用户输入文本时,通过自动机的状态转换来快速匹配敏感词。具体特征是,有一个有效状态的集合和一些从一个状态通向另一个状态的边,每条边上标记一个符号,其中一些状态是初态,一些状态是终态。只有从初态经过正确的状态转移到终态的词才能被认定为敏感词。当然我们也可以将整个DFA模型看成是树型结构,终态对应的都是叶子节点,初态可以看成是某个根节点,只有完全匹配到叶子节点才算匹配成功。最近我在设计我们线上刷题网站的时候,有一个社区讨论模块,大家可以在上面发布动态、发布评论回复,这就难免涉及到一些敏感词的评论,为了构建和谐健康的讨论社区,我们在这边需要对用户发布的评论回复内容进行敏感词的检测。那么在这种场景下,我们就考虑到了使用DFA算法来进行敏感词的快速匹配。

算法实现

DFA模型的构建

模型的构建可以看成是一棵树的构建,树的每个节点都是敏感词中的一个字符,我们以词“傻波一”为例,来构建一个DFA:

1.初始状态:S0

2.状态S1匹配到"傻"

3.状态S2匹配到"波"

4.状态S3匹配到"一"

这里我们只在谈DFA模型构建大体思路,具体使用的数据结构在这里并没有给出,说是树型结构是为了更好地理解这里面敏感词的转换逻辑。我们给出一个示意图来更直观地展示这一过程:

 

 

这是一个有两个简单敏感词地DFA模型,当匹配到的词是"傻"时进入左边的S0状态,等待下一个状态的转换触发条件,比如出现"子"或者"波"进入下一个状态,在等待状态转移的过程中,如果出现的不是"子"或者"波"那么就会回退到初态,也就是顶层节点,等待进入左边节点的S0或者右边的S0,一直到出现"子"或者连着出现了"波"和"一"这样就匹配到了终态,判定当前的词为敏感词。 

代码的构建

在这里,我们将实现构建DFA的方法、删除词库中的敏感词的方法以及使用DFA算法匹配敏感词的方法,帮助大家进一步理解。首先来说一下我们构建DFA用到的数据结构,这边主要使用一个Map集合来标示词节点,键表示为词节点,值为这个词节点后续的词节点的信息,也是同样的Map集合来存储,这个Map集合的形式和前面说的也是一致的,这就像是树节点一样:一个树的根节点是TreeNode类型,有左右孩子,然后它的左右孩子也是TreeNode。这边的思想与这个是一致的。

首先是敏感词的DFA构建,根据上面的描述,算法代码如下显示:

public class DFAFilter {
    private final Map<Character, Map> wordMap = new HashMap<>();
    public void addWord(String word) {
        Map<Character, Map> nowMap = wordMap;
        for (int i = 0; i < word.length(); i++) {
            char keyChar = word.charAt(i);
            Map<Character, Map> newWordMap = nowMap.get(keyChar);
            if (newWordMap == null) {
                newWordMap = new HashMap<>();
                nowMap.put(keyChar, newWordMap);
            }
            nowMap = newWordMap;
        }
        nowMap.put(' ', new HashMap<>()); // 使用空格字符表示 isEnd 标志
    }
}

其次是敏感词的检测,我们这边直接将输入的文本中的敏感词用*代替了,更符合显示场景的需求:

    public String containsSensitiveWord(String text){
        StringBuilder stringBuilder = new StringBuilder(text);

        List<String> result=new ArrayList<>();
        for(int i=0;i<stringBuilder.length();i++){
            Map<Character, Map> cur = wordMap;
            int startIndex=i;
            for(int j=i;j<stringBuilder.length();j++){
                char c = stringBuilder.charAt(j);
                cur=cur.get(c);
                if(cur==null)
                    break;
                if(cur.containsKey(' ')){
                    String substring = stringBuilder.substring(startIndex, j + 1);
                    if(!result.contains(substring))
                        result.add(substring);
                    i=j;
                    for(int k=startIndex;k<=j;k++){
                        stringBuilder.replace(k,k+1,"*");
                    }
                }

            }
        }
        return stringBuilder.toString();
    }

当然如果我们需要删除之前录入的敏感词,核心思想就是遍历这个Map集合,删除敏感词的最后一个词,然后回溯删除不必要的词,删除逻辑是删除那些没有后续字符并且没有终止标识符的词:

public void removeWord(Collection<String> wordList) {
        if (wordList == null || wordList.isEmpty()) {
            return;
        }

        for (String word : wordList) {
            Map<Character, Map> nowMap = wordMap;
            Stack<Map<Character, Map>> stack = new Stack<>();
            Stack<Character> charStack = new Stack<>();

            for (int i = 0; i < word.length(); i++) {
                char keyChar = word.charAt(i);
                Map<Character, Map> nextMap = nowMap.get(keyChar);
                if (nextMap == null) {
                    // 敏感词不存在
                    return;
                }
                stack.push(nowMap);
                charStack.push(keyChar);
                nowMap = nextMap;
            }

            if (nowMap.containsKey(' ')) {
                nowMap.remove(' ');
            }

            // 回溯清理无用节点
            for (int i = word.length() - 1; i >= 0; i--) {
                Map<Character, Map> currentMap = stack.pop();
                char currentChar = charStack.pop();

                // 如果当前字符对应的 Map 为空,则删除该字符节点
                if (nowMap.isEmpty()) {
                    currentMap.remove(currentChar);
                }

                nowMap = currentMap;
            }
        }
    }

那么我们完成了DFA模型的构建、利用DFA模型的状态转换思想进行敏感词检测以及删除敏感词方法。

总结

DFA算法在敏感词检测场景有着比较好的展现效果,其核心思想在于对给定敏感词构建确定性有穷自动机,这边以Map集合的形式构建了一个类似于树型结构的DFA,包括初态中间态以及终态,根据是否出现满足状态转移的条件来推进下一个状态,到达终态判定为敏感词。在我们的刷题网站中的社区模块里,用户发布动态内容和评论回复的敏感词检测就使用到了DFA算法。上面给出了我们实现的DFA算法的核心功能。

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

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

相关文章

并发处理 优先图和多重图

优先图(Precedence Graph)视图可串性多重图(Polygraph) 优先图(Precedence Graph) 优先图用于冲突可串性的判断。 优先图结构&#xff1a; 结点 (Node)&#xff1a;事务&#xff1b;有向边 (Arc): Ti → Tj &#xff0c;满足 Ti <s Tj&#xff1b; 存在Ti中的操作A1和Tj…

利用redis Zset实现 排行榜功能 配合xxl-job持久化每一个赛季的排行榜

zset 可以排序 使用xxl-job实现定时任务 对历史排行榜持久化到数据库 排行榜有当前赛季排行版和历史排行榜 当前赛季排行榜利用redis 中的SortSet 数据结构 获取 每个月的 月初 利用xxl-job的定时任务持久化化上一个月的排行榜信息 并删除redis中的数据 当排行榜数据量巨大时…

【5G VoNR】VoNR流程简述

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G技术研究。 博客内容主要围绕…

移动校园(5):课程表数据获取及展示

首先写下静态页面&#xff0c;起初打算做成一周的课表&#xff0c;由于是以小程序的形式展现&#xff0c;所以显示一周的话会很拥挤&#xff0c;所以放弃下面的方案&#xff0c;改作一次显示一天 改后结果如下&#xff0c;后期还会进行外观优化 真正困难的部分是数据获取 大家大…

拆分Transformer注意力,韩国团队让大模型解码提速20倍|大模型AI应用开始小规模稳步爆发|周伯文:大模型也有幻觉,全球AI创新指数公布

拆分Transformer注意力&#xff0c;韩国团队让大模型解码提速20倍AI正在颠覆AI上市不到两年&#xff0c;蜗牛游戏可能要退市了&#xff1f;世界人工智能大会结束了&#xff0c;百花齐放&#xff0c;但也群魔乱舞“串联OLED”被苹果带火了&#xff0c;比OLED强在哪里&#xff1f…

文化财经macd顶底背离幅图指标公式源码

DIFF:EMA(CLOSE,12) - EMA(CLOSE,26); DEA:EMA(DIFF,9); MACD:2*(DIFF-DEA),COLORSTICK; JC:CROSS(DIFF,DEA); SC:CROSSDOWN(DIFF,DEA); N1:BARSLAST(JC)1; N2:BARSLAST(SC)1; HH:VALUEWHEN(CROSSDOWN(DIFF,DEA),HHV(H,N1));//上次MACD红柱期间合约最大值 HH2:VALUEWHE…

MySQL:视图、用户管理、C/C++/图形化界面链接访问数据库、网页逻辑

文章目录 1.视图1.1 视图的基本使用1.2 视图的基本规则 2.用户管理2.1 创建、删除、修改用户2.2 数据库权限 3.C/C/图形化界面链接访问数据库3.1 准备工作及常用接口介绍3.2 图形化界面访问MySQL 4.用户逻辑(注册&&登录) 1.视图 视图是一个虚拟表&#xff0c;其内容由…

springboot苏桦旅游管理系统-计算机毕业设计源码02123

摘要 旅游业在全球范围内不断发展&#xff0c;为了提供高效的旅游管理和服务&#xff0c;开发一个旅游管理系统具有重要意义。本文旨在设计和实现该旅游管理系统&#xff0c;以满足用户和管理员的需求。该系统采用Spring Boot作为后端框架&#xff0c;利用其简化的开发流程和强…

ComfyUI如何高效率使用多Lora

Efficient 工作流 {"last_node_id": 29,"last_link_id": 56,"nodes": [{"id": 26,"type": "LoRA Stacker","pos": [540,270],"size": {"0": 320,"1": 322},"flag…

如何让代码兼容 Python 2 和 Python 3?Future 库助你一臂之力

目录 01Future 是什么? 为什么选择 Future? 安装与配置 02Future 的基本用法 1、兼容 print 函数 2、兼容整数除法 3、兼容 Unicode 字符串 03Future 的高级功能 1. 处理字符串与字节 2. 统一异常处理…

STM32-TIM定时器

本内容基于江协科技STM32视频内容&#xff0c;整理而得。 文章目录 1. TIM1.1 TIM定时器1.2 定时器类型1.3 基本定时器1.4 通用定时器1.4 高级定时器1.5 定时中断基本结构1.6 预分频器时序1.7 计数器时序1.8 计数器无预装时序1.9 计数器有预装时序1.10 RCC时钟树 2. TIM库函数…

路径跟踪算法之PID、PP、Stanley详细理解

一、前言 今天又来补作业了&#xff01; 在跟踪控制领域&#xff0c;PID&#xff08;Proportional-Integral-Derivative, 分别为比例、积分、微分&#xff09;、PP&#xff08; Pure-Puresuit, 纯跟踪&#xff09;、Stanley&#xff08;前轮反馈控制&#xff09;是三种最为常见…

02STM32软件安装新建工程

STM32软件安装&新建工程 1.软件安装&#xff1a;1.1Keil5 MDK安装1.2安装器件支持包离线安装支持包在线安装支持包 1.3软件注册&#xff1a;1.4安装驱动STLINK驱动JLink驱动在此文件夹下USB转串口 2开发方式&新建工程步骤&架构2.1STM32开发方式&#xff1a;库函数压…

线性系统理论及应用GUI设计及仿真

目录 1.控制系统的状态空间模型 1.1.状态空间模型 1.2 传递函数模型 1.3 传递函数转换为状态空间模型 1.4.状态空间模型转换为传递函数 1.5.状态空间模型转化为约当标准型 2.线性系统的时域分析 2.1.矩阵指数函数的计算 2.2.线型定常连续系统的状态空间模型求解 3.线…

《Nature》文章:ChatGPT帮助我学术写作的三种方式

图片翻译 ** 文章内容** 忏悔时间&#xff1a;我使用生成式人工智能&#xff08;AI&#xff09;。尽管在学术界关于聊天机器人是积极力量还是消极力量的争论不休&#xff0c;但我几乎每天都使用这些工具来完善我所写论文中的措辞&#xff0c;并寻求对我被要求评估的工作进行替…

Mysql-常用函数及其用法总结

1、字符串函数 测试用例如下&#xff1a; 1.1 CONCAT() 将多个字符串连接成一个字符串。 SELECT CONCAT(first_name, , last_name) AS full_name FROM users; -- 期望结果&#xff1a;John Doe, Jane Smith, Michael Johnson 1.2 SUBSTRING() 提取子字符串 SELECT SUBSTR…

算法012:将x减到0的最小操作数

将x减到0的最小操作数. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/ 这个题使用到的是滑动窗口。 乍一看&#xff0c…

纹波和噪声的介绍以及区别

纹波和噪声的介绍 纹波和噪声都是在电源输出中出现的信号波动&#xff0c;但两者存在明显的区别。   纹波&#xff1a;是附着于直流电平之上的包含周期性与随机性成分的杂波信号。在额定输出电压、电流的情况下&#xff0c;纹波指的是输出电压中的交流电压的峰值 。狭义上的纹…

生产调度:flowshop问题数学建模

接上一篇文章&#xff0c;在了解生产调度问题的背景和基本概念之后&#xff0c;我想先从比较基础的 flowshop和 jobshop 数学模型入手&#xff0c;理解实际调度过程中的问题求解思路。这一篇文章主要面向 flowshop 问题进行数学建模&#xff0c;对于这类比较经典的问题&#xf…

大语言模型基础

大语言基础 GPT : Improving Language Understanding by Generative Pre-Training 提出背景 从原始文本中有效学习的能力对于减轻自然语言处理中对监督学习的依赖至关重要。很多深度学习方法需要大量人工标注的数据&#xff0c;限制了它们在很多领域的应用&#xff0c;收集更…