手把手教你java快速过滤关键词

java过滤关键词

敏感词、文字过滤是一个网站必不可少的功能,如何设计一个好的、高效的过滤算法是非常有必要的。前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢。我把它程序拿过来一看,整个过程如下:读取敏感词库、如果HashSet集合中,获取页面上传文字,然后进行匹配。我就想这个过程肯定是非常慢的。对于他这个没有接触的人来说我想也只能想到这个,更高级点就是正则表达式。但是非常遗憾,这两种方法都是不可行的。当然,在我意识里没有我也没有认知到那个算法可以解决问题,但是Google知道!

DFA简介

在实现文字过滤的算法中,DFA是唯一比较好的实现算法。DFA即Deterministic Finite Automaton,也就是确定有穷自动机,它是是通过event和当前的state得到下一个state,即event+state=nextstate。下图展示了其状态的转换

在这里插入图片描述
在这幅图中大写字母(S、U、V、Q)都是状态,小写字母a、b为动作。通过上图我们可以看到如下关系

a b b
S -----> U S -----> V U -----> V

在实现敏感词过滤的算法中,我们必须要减少运算,而DFA在DFA算法中几乎没有什么计算,有的只是状态的转换。

在这里插入图片描述

Java实现DFA算法实现敏感词过滤

在Java中实现敏感词过滤的关键就是DFA算法的实现。首先我们对上图进行剖析。在这过程中我们认为下面这种结构会更加清晰明了。
在这里插入图片描述
同时这里没有状态转换,没有动作,有的只是Query(查找)。我们可以认为,通过S query U、V,通过U query V、P,通过V query U P。通过这样的转变我们可以将状态的转换转变为使用Java集合的查找。

诚然,加入在我们的敏感词库中存在如下几个敏感词:日本人、日本鬼子、毛.泽.东。那么我需要构建成一个什么样的结构呢?

首先:query 日 —> {本}、query 本 —>{人、鬼子}、query 人 —>{null}、query 鬼 —> {子}。形如下结构:

在这里插入图片描述

     下面我们在对这图进行扩展:

在这里插入图片描述
这样我们就将我们的敏感词库构建成了一个类似与一颗一颗的树,这样我们判断一个词是否为敏感词时就大大减少了检索的匹配范围。比如我们要判断日本人,根据第一个字我们就可以确认需要检索的是那棵树,然后再在这棵树中进行检索。

     但是如何来判断一个敏感词已经结束了呢?利用标识位来判断。

所以对于这个关键是如何来构建一棵棵这样的敏感词树。下面我已Java中的HashMap为例来实现DFA算法。具体过程如下:

日本人,日本鬼子为例

1、在hashMap中查询“日”看其是否在hashMap中存在,如果不存在,则证明已“日”开头的敏感词还不存在,则我们直接构建这样的一棵树。跳至3。

2、如果在hashMap中查找到了,表明存在以“日”开头的敏感词,设置hashMap = hashMap.get(“日”),跳至1,依次匹配“本”、“人”。

3、判断该字是否为该词中的最后一个字。若是表示敏感词结束,设置标志位isEnd = 1,否则设置标志位isEnd = 0;

在这里插入图片描述
程序实现如下:

/*** 读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:<br>* 中 = {*      isEnd = 0*      国 = {<br>*           isEnd = 0*           人 = {isEnd = 0*                民 = {isEnd = 1}*                }*           男  = {*                  isEnd = 0*                   人 = {*                        isEnd = 1*                       }*               }*           }*      }*  五 = {*      isEnd = 0*      星 = {*          isEnd = 0*          红 = {*              isEnd = 0*              旗 = {*                   isEnd = 1*                  }*              }*          }*      }最新2020整理收集的很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,需要获取这些内容的朋友加QQ群:756584822* @author chenming * @date 2014年4月20日 下午3:04:20* @param keyWordSet  敏感词库* @version 1.0*/@SuppressWarnings({ "rawtypes", "unchecked" })private void addSensitiveWordToHashMap(Set<String> keyWordSet) {sensitiveWordMap = new HashMap(keyWordSet.size());     //初始化敏感词容器,减少扩容操作String key = null;  Map nowMap = null;Map<String, String> newWorMap = null;//迭代keyWordSetIterator<String> iterator = keyWordSet.iterator();while(iterator.hasNext()){key = iterator.next();    //关键字nowMap = sensitiveWordMap;for(int i = 0 ; i < key.length() ; i++){char keyChar = key.charAt(i);       //转换成char型Object wordMap = nowMap.get(keyChar);       //获取if(wordMap != null){        //如果存在该key,直接赋值nowMap = (Map) wordMap;}else{     //不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个newWorMap = new HashMap<String,String>();newWorMap.put("isEnd", "0");     //不是最后一个nowMap.put(keyChar, newWorMap);nowMap = newWorMap;}if(i == key.length() - 1){nowMap.put("isEnd", "1");    //最后一个}}最新2020整理收集的很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,需要获取这些内容的朋友加Q君样:756584822}}

运行得到的hashMap结构如下:

{五={星={红={isEnd=0, 旗={isEnd=1}}, isEnd=0}, isEnd=0}, 中={isEnd=0, 国={isEnd=0, 人={isEnd=1}, 男={isEnd=0, 人={isEnd=1}}}}}

敏感词库我们一个简单的方法给实现了,那么如何实现检索呢?检索过程无非就是hashMap的get实现,找到就证明该词为敏感词,否则不为敏感词。过程如下:假如我们匹配“中国人民万岁”。

1、第一个字“中”,我们在hashMap中可以找到。得到一个新的map = hashMap.get("")。

2、如果map == null,则不是敏感词。否则跳至3

3、获取map中的isEnd,通过isEnd是否等于1来判断该词是否为最后一个。如果isEnd == 1表示该词为敏感词,否则跳至1。

通过这个步骤我们可以判断“中国人民”为敏感词,但是如果我们输入“中国女人”则不是敏感词了。

/*** 检查文字中是否包含敏感字符,检查规则如下:<br>* @author chenming * @date 2014年4月20日 下午4:31:03* @param txt* @param beginIndex* @param matchType* @return,如果存在,则返回敏感词字符的长度,不存在返回0* @version 1.0*/@SuppressWarnings({ "rawtypes"})public int CheckSensitiveWord(String txt,int beginIndex,int matchType){boolean  flag = false;    //敏感词结束标识位:用于敏感词只有1位的情况int matchFlag = 0;     //匹配标识数默认为0char word = 0;Map nowMap = sensitiveWordMap;for(int i = beginIndex; i < txt.length() ; i++){word = txt.charAt(i);nowMap = (Map) nowMap.get(word);     //获取指定keyif(nowMap != null){     //存在,则判断是否为最后一个matchFlag++;     //找到相应key,匹配标识+1 if("1".equals(nowMap.get("isEnd"))){       //如果为最后一个匹配规则,结束循环,返回匹配标识数flag = true;       //结束标志位为true   if(SensitivewordFilter.minMatchTYpe == matchType){    //最小规则,直接返回,最大规则还需继续查找最新2020整理收集的很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,需要获取这些内容的朋友加Q君样:756584822break;}}}else{     //不存在,直接返回break;}}if(matchFlag < 2 && !flag){     matchFlag = 0;}return matchFlag;}
/*** 检查文字中是否包含敏感字符,检查规则如下:<br>* @author chenming * @date 2014年4月20日 下午4:31:03* @param txt* @param beginIndex* @param matchType* @return,如果存在,则返回敏感词字符的长度,不存在返回0* @version 1.0*/@SuppressWarnings({ "rawtypes"})public int CheckSensitiveWord(String txt,int beginIndex,int matchType){boolean  flag = false;    //敏感词结束标识位:用于敏感词只有1位的情况int matchFlag = 0;     //匹配标识数默认为0char word = 0;Map nowMap = sensitiveWordMap;for(int i = beginIndex; i < txt.length() ; i++){word = txt.charAt(i);nowMap = (Map) nowMap.get(word);     //获取指定keyif(nowMap != null){     //存在,则判断是否为最后一个matchFlag++;     //找到相应key,匹配标识+1 if("1".equals(nowMap.get("isEnd"))){       //如果为最后一个匹配规则,结束循环,返回匹配标识数flag = true;       //结束标志位为true   if(SensitivewordFilter.minMatchTYpe == matchType){    //最小规则,直接返回,最大规则还需继续查找最新2020整理收集的很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,需要获取这些内容的朋友加Q君样:756584822break;}}}else{     //不存在,直接返回break;}}if(matchFlag < 2 && !flag){     matchFlag = 0;}return matchFlag;}

运行结果:

在这里插入图片描述

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

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

相关文章

[Delphi]根据输入日期按年月周日输出日期段

输入变量ADateStart&#xff0c;并为其填写起始日期&#xff0c;变量ADateEnd&#xff0c;计算类型AType&#xff0c;输出变量ADateStart&#xff0c;变量ADateEnd procedureFormatDateByType(AType:Integer; varADateStart, ADateEnd: TDate); var//type0日 1周 2月 3年 …

TIOBE 发布 8 月编程语言榜单:C# 排名如何?

刚刚 TIOBE 官方最新发布了 8 月的编程语言榜单&#xff0c;一起来看本月榜单中有什么值得关注的发展趋势吧&#xff1f;每一种编程语言的兴起从来都离不开它所适用的技术领域&#xff0c;二者之间一直以来都是水涨船高的关系。数据挖掘和人工智能的蓬勃发展也是如此&#xff0…

两年了,你还是那个你 | 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源都市音酱&#xff0c;侵权删&#xff09;

Delphi 的字符及字符串[4] - 字符串、字符指针与字符数组

//字符串 < > 字符数组 vararr: array[0..5] of Char;str: string; begin{可以把字符串常量直接赋给字符数组; 但超界不行}arr : Delphi;ShowMessage(arr); {Delphi}{可以把字符数组直接赋给字符串变量}str : arr;ShowMessage(str); {Delphi}{其实字符串内部也是包含了一…

职场智慧之如何提升自己在公司的价值

一个人要想在公司立足&#xff0c;成为公司不可或缺的人才&#xff0c;并得到公司的重用和青睐&#xff0c;只有让自己对公司具有更大的价值&#xff0c;那么如何提升自己在公司的价值呢&#xff1f;1&#xff0e;任务分配&#xff0c;不怕累&#xff0c;多干活任何公司、老总都…

Java IO(一)

【例1】创建一个新文件import java.io.*; class hello{public static void main(String[] args) {File fnew File("D:\\hello.txt");try{f.createNewFile();}catch (Exception e) {e.printStackTrace();}} }【运行结果】&#xff1a;程序运行后&#xff0c;在D盘下会…

Java Dao模式通过JDBC连接数据库的操作

Java程序访问数据库&#xff1a; 1、获取数据库厂商提供的驱动&#xff08;jdbc接口的实现类&#xff09; 如ojdbc14.jar——Oracle数据库驱动jar包 mysql-connector-java-5.1.8-bin.jar——MySQL数据库驱动jar包 自己去网上下载就行。 2、使用JDBC的API访问数据库 连接、…

k8s入门你至少需要会哪些

前言相信很多公司都有集成发布pass系统&#xff0c;底层大多数依赖于k8s来进行服务的发布部署/回滚等功能。对于很多业务开发者都是不可见的&#xff0c;在感叹这个东西真好用的同时&#xff0c;想着探一探这背后的原理。今天这篇k8s入门我整理了必会的几个k8s知识点&#xff0…

Windows CE的电源管理之三

本篇将以Windows Mobile为例介绍Windows CE电源管理的实现&#xff0c;大体上&#xff0c;Windows Mobile分为Pocket PC和Smartphone两种版本。这两者之间的主要区别在于触摸屏和电源模型&#xff0c;Smartphone采用的是“Always On”模型。为了说清楚它们的区别&#xff0c;我…

跟你们讲一个鬼故事,TA回来了!

全世界只有3.14 % 的人关注了青少年数学之旅真正决定人与人之间的差距的&#xff0c;其实是我们对事物的见识与内心的格局&#xff0c;见识的深浅决定人生的深浅&#xff0c;格局的大小决定了人生之路是宽是窄。今天给大家推荐几个有深度、有想法的公众号&#xff0c;希望能够给…

java之static关键词的作用

static关键词的作用 1、静态成员变量的语法特定 2、静态函数的语法特定 3、静态代码块的语法特定 定义静态成员变量 Person.java class Person{ static int a; }按照以前可以这么调用 public class Test1{ public static void main(String[] args){ Person person new Per…

分布式事务最终一致性-CAP框架轻松搞定

前言对于分布式事务&#xff0c;常用的解决方案根据一致性的程度可以进行如下划分&#xff1a;强一致性(2PC、3PC)&#xff1a;数据库层面的实现&#xff0c;通过锁定资源&#xff0c;牺牲可用性&#xff0c;保证数据的强一致性&#xff0c;效率相对比较低。弱一致性(TCC)&…

Cus系统beta1.2发布

2019独角兽企业重金招聘Python工程师标准>>> 经过小伙伴的努力&#xff0c;Cus后台管理系统开发完成&#xff0c;完善了后台系统&#xff0c;权限控制&#xff0c;新闻发布&#xff0c;商务合作等等功能 主要功能包括&#xff1a; 后台系统截图 更多后台系统截图请点…

如何打开网页链接

System.Diagnostics.Process.Start("http://news.163.com") 转载于:https://www.cnblogs.com/habin/archive/2008/03/10/1099285.html

区区6位密码,凭什么守护我的百万家产?

全世界只有3.14 % 的人关注了青少年数学之旅今天超模君非常的开心你问为什么&#xff1f;当然是——又双叒可以买新的数学书好开心&#xff01;不过在这欢快的气氛中超模君却听见了小天的叹气声玩笑归玩笑但是银行的密码系统真很安全的吗&#xff1f;今天我们就来讨论下密码学的…

在ie6下实现position-fixed的效果--------续集---对联效果(02)

在ie6下实现position-fixed的效果&#xff0c;这回是实现的对联效果&#xff0c;没有JS在里面的对联效果&#xff0c;但是没有JS的动感。 这个的原理是和《在ie6下实现position-fixed的效果》的是一样的。CSS&#xff1a;1 <style type"text/css">2 *{margin:0…

狐狸和猫

一只猫在森林里遇到一只狐狸&#xff0c;心想&#xff1a;"他又聪明&#xff0c;经验又丰富&#xff0c;挺受人尊重的。"于是它很友好地和狐狸打招呼&#xff1a;"日安&#xff0c;尊敬的狐狸先生&#xff0c;您好吗&#xff1f;这些日子挺艰难的&#xff0c;您…

Java开发之上班摸鱼!写最少的代码!

I 前言 本次分享一下我所知道的如何写最少的代码的小技巧&#xff0c;如果你有更好的方案&#xff0c;欢迎在评论区留言&#xff0c;方案很棒的话&#xff0c;加我交流圈&#xff0c;为你送上冬天的一杯奶茶~ Java&#xff1a;我想返回多个返回值 秀一下Go的多返回值&#xf…

Windows 11 预览版 Build 22000.120 发布

微软现已发布第五个 Windows 11 预览版更新 KB5005188&#xff0c;版本号升级至 Build 22000.120。本次更新面向 Dev 频道和 Beta 频道的 Windows 预览体验成员推出。Windows 11 Insider Preview Build 22000.120 主要变化如下&#xff1a;1.全新的 Family Safety&#xff08;家…

经典SQL语句集锦

来自网络下列语句部分是MsSql语句&#xff0c;不可以在access中使用。SQL分类&#xff1a; DDL—数据定义语言(CREATE&#xff0c;ALTER&#xff0c;DROP&#xff0c;DECLARE) DML—数据操纵语言(SELECT&#xff0c;DELETE&#xff0c;UPDATE&#xff0c;INSERT) DCL—数据控制…