一、DFA 算法简介

在实现文字过滤的算法中,DFA是唯一比较好的实现算法。

DFA 全称为:Deterministic Finite Automaton,即确定有穷自动机。其特征为:有一个有限状态集合和一些从一个状态通向另一个状态的边,每条边上标记有一个符号,其中一个状态是初态,某些状态是终态。但不同于不确定的有限自动机,DFA 中不会有从同一状态出发的两条边标志有相同的符号。

简单点说就是,它是是通过 event 和当前的 state 得到下一个 state,即 event + state= nextstate。理解为系统中有多个节点,通过传递进入的 event,来确定走哪个路由至另一个节点,而节点是有限的。

二、DEA 算法实践敏感词过滤

1. 敏感词库构造

以王八蛋和王八羔子两个敏感词来进行描述,首先构建敏感词库,该词库名称为SensitiveMap,这两个词的二叉树构造为:

用 hash 表构造为:

{
"王":{
"isEnd":"0",
"八":{
"羔":{
"子":{
"isEnd":"1"
},
"isEnd":"0"
},
"isEnd":"0",
"蛋":{
"isEnd":"1"
}
}
}
}

怎么用代码实现这种数据结构呢?

    /**
* 读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型
*
* @param keyWordSet 敏感词库
*/
public Map<String, Object> addSensitiveWordToHashMap(Set<String> keyWordSet) {
//初始化敏感词容器,减少扩容操作
Map<String, Object> map = new HashMap(Math.max((int) (keyWordSet.size() / .75f) + 1, 16));
//迭代keyWordSet
for (String aKeyWordSet : keyWordSet) {
Map nowMap = map;
for (int i = 0; i < aKeyWordSet.length(); i++) {
//转换成char型
char keyChar = aKeyWordSet.charAt(i);
//获取
Object wordMap = nowMap.get(keyChar);
//如果存在该key,直接赋值
if (wordMap != null) {
nowMap = (Map) wordMap;
} else { //不存在则,则构建一个map,同时将isEnd设置为0
Map<String, String> newWorMap = new HashMap<>(3);
newWorMap.put("isEnd", "0");
nowMap.put(keyChar, newWorMap);
nowMap = newWorMap;
}
//判断最后一个
if (i == aKeyWordSet.length() - 1) {
nowMap.put("isEnd", "1");
}
}
}
return map;
}

2. 敏感词过滤

以上面例子构造出来的 SensitiveMap 为敏感词库进行示意,假设这里输入的关键字为:王八不好,流程图如下:

怎么用代码实现这个流程图逻辑呢?

    /**
* 查找字符串中是否包含敏感字符
*
* @param txt 输入的字符串
* @return 如果存在,则返回敏感字符串;不存在,则返回空字符串
*/
public static String findSensitiveWord(String txt) {
SensitiveWordInit sensitiveWordInit = SpringContextHolder.getBean(SensitiveWordInit.class);
Map<String, Object> sensitiveWordMap = sensitiveWordInit.getSensitiveWordMap();
StringBuilder sensitiveWord = new StringBuilder();
// 敏感词结束标志位,表示匹配到了最后一位
boolean flag = false;
for (int i = 0; i < txt.length(); i++) {
char word = txt.charAt(i);
// 获取指定 key
sensitiveWordMap = (Map) sensitiveWordMap.get(word);
// 不存在,直接返回没有敏感词
if (sensitiveWordMap == null) {
break;
}
//存在,存储该敏感词,并判断是否为最后一个
sensitiveWord.append(word);
//如果为最后一个匹配规则,结束循环
if ("1".equals(sensitiveWordMap.get("isEnd"))) {
flag = true;
break;
}
}
// 表示匹配到了完整敏感词
if (flag == true) {
return sensitiveWord.toString();
}
return "";
}

三、优化思路

对于“王*八&&蛋”这样的词,中间填充了无意义的字符来混淆,在我们做敏感词搜索时,同样应该做一个无意义词的过滤,当循环到这类无意义的字符时进行跳过,避免干扰。

利用 DFA 算法实现文字过滤的更多相关文章

  1. Java 利用DFA算法 屏蔽敏感词

    原文:http://www.open-open.com/code/view/1435214601278 import java.io.BufferedReader; import java.io.Fi ...

  2. 敏感词过滤的算法原理之DFA算法

    参考文档 http://blog.csdn.net/chenssy/article/details/26961957 敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有 ...

  3. java实现敏感词过滤(DFA算法)

    小Alan在最近的开发中遇到了敏感词过滤,便去网上查阅了很多敏感词过滤的资料,在这里也和大家分享一下自己的理解. 敏感词过滤应该是不用给大家过多的解释吧?讲白了就是你在项目中输入某些字(比如输入xxo ...

  4. Java过滤敏感词语/词汇---DFA算法

    最近网站需要在评论.投稿等地方过滤敏感词汇,于是在网上查找了相关教程,特此整理分享. 关于DFA算法,详细的可以去http://blog.csdn.net/u013378306/article/det ...

  5. Java实现敏感词过滤 - DFA算法

    Java实现DFA算法进行敏感词过滤 封装工具类如下: 使用前需对敏感词库进行初始化: SensitiveWordUtil.init(sensitiveWordSet); package cn.swf ...

  6. 使用DFA算法对敏感词进行过滤

    项目目录结构如下: 其中resources资源目录中: stopwd.txt :停顿词,匹配时间直接过滤. wd.txt:敏感词库. 1.WordFilter敏感词过滤类: package com.s ...

  7. 敏感词汇过滤DFA算法

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...

  8. 基于DFA算法、RegExp对象和vee-validate实现前端敏感词过滤

    面临敏感词过滤的问题,最简单的方案就是对要检测的文本,遍历所有敏感词,逐个检测输入的文本是否包含指定的敏感词. 很明显上面这种实现方法的检测时间会随着敏感词库数量的增加而线性增加.系统会因此面临性能和 ...

  9. DFA算法实现敏感词过滤

    DFA算法:即确定有穷自动机,简单点说就是,它是是通过event和当前的state得到下一个state,即event+state=nextstate.理解为系统中有多个节点,通过传递进入的event, ...

随机推荐

  1. Spring框架AOP学习总结(下)

    目录 1. AOP 的概述 2. Spring 基于AspectJ 进行 AOP 的开发入门(XML 的方式): 3.Spring 基于AspectJ 进行 AOP 的开发入门(注解的方式): 4.S ...

  2. 【集训Day1 测试】奇怪数

    奇怪数(odometer) [题目描述] 一个正整数Z是奇怪数,当且仅当满足的条件是:Z的所有数字中,只有一个数字不同于其他数字.例如:33323.110 都是奇怪数,而 9779.5555 都不是奇 ...

  3. linux runlevel运行级别

    1.linux通过设定runlevel来设定系统使用不同的服务启动,从而使得linux运行的环境有所不同. 2.当系统启动后会按照以下步骤完成初始化:运行/sbin/init程序加载器配置文件/etc ...

  4. 使用scrapy-redis搭建分布式爬虫环境

    scrapy-redis简介 scrapy-redis是scrapy框架基于redis数据库的组件,用于scrapy项目的分布式开发和部署. 有如下特征:  分布式爬取 您可以启动多个spider工 ...

  5. Unicode和Ascii的区别

    计算机只能处理数字,如果要处理文本,就必须把文本转换成数字.    最早的计算机设计采用8bit作为一个字节,所以,一个字节只能表示的最大整数255.   0-255被用来表示数字和一些符号,这个编码 ...

  6. Fragment事务管理源码分析

    转载请标明出处:http://blog.csdn.net/shensky711/article/details/53132952 本文出自: [HansChen的博客] 概述 在Fragment使用中 ...

  7. NIO-Buffeer

    目录 NIO-Buffeer 目录 什么是Buffer 缓冲区类型 缓冲区存储类型 字节存放顺序 Buffer使用 Buffer ByteBuffer 总结 相关文献 NIO-Buffeer 目录 N ...

  8. react之context

    context是什么 Props属性是由上到下单向传递的 context提供了在组件中共享此类值的方法 context使用 设计目的是共享哪些对于组件来说全局的数据 不要因为仅仅为了避免在几个层级下的 ...

  9. zsh: /usr/local/bin/pod: bad interpreter: /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby: no such file or directory

    系统升级为 macOS Catalina 发现 CocoaPods 不管用了. 解决方法: 打开 iTerm2 sudo gem update --system 输入电脑密码,然后 sudo gem ...

  10. PHP自动发红包代码示例

    <?php header('Content-type:text'); define("TOKEN", "weixin"); $wechatObj = ne ...