敏感词匹配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算法的核心功能。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VuePress 的更多配置

现在&#xff0c;读者应该对 VuePress、主题和插件等有了基本的认识&#xff0c;除了插件&#xff0c;VuePress 自身也有很多有用的配置&#xff0c;这里简单说明下。 ‍ ‍ VuePress 的介绍 在介绍了 VuePress 的基本使用、主题和插件的概念之后&#xff0c;我们再来看看官…

简介空间复杂度

我们承接上一篇博客。我们写了时间复杂度之后&#xff0c;我们就要来介绍一下另一个相关复杂度了。空间复杂度。我觉得大家应该对空间复杂度认识可能比较少一些。我就是这样&#xff0c;我很少看见题目中有明确要求过空间复杂度的。但确实有这个是我们不可忽视的&#xff0c;所…

PXIe-7976【K410T】

起售价 RMB 152,880.00 块RAM(BRAM): 28620 kbit 动态RAM(DRAM): 2 GB FPGA: Kintex-7 410T PXI背板链路: PCI-Express Gen2 x 8 FPGA片: 63550 DSP片: 1540

ChatGPT-4o大语言模型优化、本地私有化部署、从0-1搭建、智能体构建等高级进阶

目录 第一章 ChatGPT-4o使用进阶 第二章 大语言模型原理详解 第三章 大语言模型优化 第四章 开源大语言模型及本地部署 第五章 从0到1搭建第一个大语言模型 第六章 智能体&#xff08;Agent&#xff09;构建 第七章 大语言模型发展趋势 第八章 总结与答疑讨论 更多应用…

昇思25天学习打卡营第12天|FCN图像语义分割

文章目录 昇思MindSpore应用实践基于MindSpore的FCN图像语义分割1、FCN 图像分割简介2、构建 FCN 模型3、数据预处理4、模型训练自定义评价指标 Metrics 5、模型推理结果 Reference 昇思MindSpore应用实践 本系列文章主要用于记录昇思25天学习打卡营的学习心得。 基于MindSpo…

LaTeX教程(014)-LaTeX文档结构(14)

LaTeX教程(014)- LaTeX \LaTeX LATE​X文档结构(14) 2.3.3 multitoc - 将目录设置为多栏 multitoc包的使用方法相当简单&#xff0c;只需要调用这个包&#xff0c;并将要设置为多栏(默认是双栏)的目录指定到包选项中即可。如\usepackage[toc]{multitoc}&#xff0c;设置的就是…

Springboot使用WebSocket发送消息

1. 创建springboot项目&#xff0c;引入spring-boot-starter-websocket依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>完整项目依赖 <?xml ver…

Vue 使用 @click 绑定点击事件

https://andi.cn/page/621505.html

Python【打包exe文件两步到位】

Python打包Exe 安装 pyinstaller&#xff08;pip install pyinstaller&#xff09; 执行打包命令&#xff08;pyinstaller demo.py&#xff09; 打完包会生成 dist 文件夹&#xff0c;如下如

基于开源AI数据框架LlamaIndex构建上下文增强型LLA应用

引言 “将你的企业数据转化为可用于实际生产环境的LLM应用程序&#xff0c;”LlamaIndex主页用60号字体这样高亮显示。其副标题是“LlamaIndex是构建LLM应用程序的领先数据框架。”我不太确定它是否是业内领先的数据框架&#xff0c;但我认为它是一个与LangChain和Semantic Ker…

快行线冷链——创新仓配、共赢未来 主题沙龙在京成功举办

2024年7月7日下午&#xff0c;由京营建联盟、北京市大兴区餐饮行业协会、北京快行线冷链物流联合主办的“创新仓配&#xff0c;共赢未来——相信拥抱的力量”主题沙龙活动在北京篝野城市露营空间隆重举行。本次活动定向邀请了餐饮老板、餐饮企业供应链负责人及冻品经销商和相关…

电子电气架构 --- 智能座舱万物互联

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

C语言指针函数指针

跟着这篇文章重新理解了一下&#xff1a;彻底攻克C语言指针 有一个例子感觉可以拿出来看看&#xff1a; char *(*c[10])(int **p); * 这段声明定义了一个长度为10的数组c&#xff0c;数组中的每个元素都是指向函数的指针。每个函数接受一个类型为int **&#xff08;指向指向…

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

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

智能物联网鱼缸

硬件部分及接线图 工具 继电器、开发板、物联网os、云平台 微信小程序 结构&#xff1a;images、pages两个为主体。 标题头部分 <view class"container"> <view class"head_box"> <image src"/images/面性鱼缸.png"><…

【C++】 解决 C++ 语言报错:Invalid Use of Incomplete Type

文章目录 引言 在 C 编程中&#xff0c;“Invalid Use of Incomplete Type” 是一种常见错误。此错误通常在程序试图使用未完全定义的类或结构时发生。这种错误不仅会导致编译失败&#xff0c;还可能导致程序行为不可预测。本文将详细探讨无效使用不完整类型的成因、检测方法及…

【Threejs进阶教程-优化篇】4.Vue/React与threejs如何解决冲突和卡顿(续)

Vue/React与threejs如何解决冲突和卡顿-续 使用说明核心思路环境搭建(vuethree)vue运行机制分析业务分离使用threejs做背景 3D模块封装使用ES6的Class来让逻辑性更强Threejs尽量按需引入创建一个类扩展写法本次代码执行顺序 扩展内容添加orbitControls和辅助线解决事件覆盖 与V…

Java请求webService,IDEA生成客户端调用代码

Axis是Apache开放源代码组织的一个项目&#xff0c;全称为Apache Extensible Interaction System&#xff0c;简称Axis。它是一个基于Java的SOAP&#xff08;Simple Object Access Protocol&#xff0c;简单对象访问协议&#xff09;引擎&#xff0c;提供创建服务器端、客户端和…

LabVIEW的Actor Framework (AF) 结构介绍

LabVIEW的Actor Framework (AF) 是一种高级架构&#xff0c;用于开发并发、可扩展和模块化的应用程序。通过面向对象编程&#xff08;OOP&#xff09;和消息传递机制&#xff0c;AF结构实现了高效的任务管理和数据处理。其主要特点包括并发执行、动态可扩展性和强大的错误处理能…

ROS——多个海龟追踪一个海龟实验

目标 通过键盘控制一个海龟&#xff08;领航龟&#xff09;的移动&#xff0c;其余生成的海龟通过监听实现追踪定期获取领航龟和其余龟的坐标信息&#xff0c;通过广播告知其余龟&#xff0c;进行相应移动其余龟负责监听 疑惑点&#xff08;已解决&#xff09; int main(int…