项目目录结构如下:

其中resources资源目录中:

stopwd.txt :停顿词,匹配时间直接过滤。

wd.txt:敏感词库。

1、WordFilter敏感词过滤类:

  1 package com.skyer.sensitivewdfilter;
  2
  3 import java.io.BufferedReader;
  4 import java.io.IOException;
  5 import java.io.InputStreamReader;
  6 import java.util.ArrayList;
  7 import java.util.HashMap;
  8 import java.util.HashSet;
  9 import java.util.List;
 10 import java.util.Map;
 11 import java.util.Set;
 12
 13 /**
 14  * 思路: 创建一个FilterSet,枚举了0~65535的所有char是否是某个敏感词开头的状态
 15  *
 16  * 判断是否是 敏感词开头 | | 是 不是 获取头节点 OK--下一个字 然后逐级遍历,DFA算法
 17  */
 18 public class WordFilter {
 19
 20     private static final FilterSet set = new FilterSet(); // 存储首字
 21     private static final Map<Integer, WordNode> nodes = new HashMap<Integer, WordNode>(1024, 1); // 存储节点
 22     private static final Set<Integer> stopwdSet = new HashSet<Integer>(); // 停顿词
 23     private static final char SIGN = '*'; // 敏感词过滤替换
 24
 25     static {
 26         try {
 27             long a = System.nanoTime();
 28             init();
 29             a = System.nanoTime() - a;
 30             System.out.println("加载时间 : " + a + "ns");
 31             System.out.println("加载时间 : " + a / 1000000 + "ms");
 32         } catch (Exception e) {
 33             throw new RuntimeException("初始化过滤器失败");
 34         }
 35     }
 36
 37     private static void init() {
 38         // 获取敏感词
 39         addSensitiveWord(readWordFromFile("wd.txt"));
 40         addStopWord(readWordFromFile("stopwd.txt"));
 41     }
 42
 43     /**
 44      * 增加敏感词
 45      */
 46     private static List<String> readWordFromFile(String path) {
 47         List<String> words;
 48         BufferedReader br = null;
 49         try {
 50             br = new BufferedReader(new InputStreamReader(WordFilter.class.getClassLoader().getResourceAsStream(path)));
 51             words = new ArrayList<String>(1200);
 52             for (String buf = ""; (buf = br.readLine()) != null;) {
 53                 if (buf == null || buf.trim().equals(""))
 54                     continue;
 55                 words.add(buf);
 56             }
 57         } catch (Exception e) {
 58             throw new RuntimeException(e);
 59         } finally {
 60             try {
 61                 if (br != null)
 62                     br.close();
 63             } catch (IOException e) {
 64             }
 65         }
 66         return words;
 67     }
 68
 69     /**
 70      * 增加停顿词
 71      */
 72     private static void addStopWord(final List<String> words) {
 73         if (words != null && words.size() > 0) {
 74             char[] chs;
 75             for (String curr : words) {
 76                 chs = curr.toCharArray();
 77                 for (char c : chs) {
 78                     stopwdSet.add(charConvert(c));
 79                 }
 80             }
 81         }
 82     }
 83
 84     /**
 85      * 添加DFA节点
 86      */
 87     private static void addSensitiveWord(final List<String> words) {
 88         if (words != null && words.size() > 0) {
 89             char[] chs;
 90             int fchar;
 91             int lastIndex;
 92             WordNode fnode; // 首字母节点
 93             for (String curr : words) {
 94                 chs = curr.toCharArray();
 95                 fchar = charConvert(chs[0]);
 96                 if (!set.contains(fchar)) {// 没有首字定义
 97                     set.add(fchar);// 首字标志位 可重复add
 98                     fnode = new WordNode(fchar, chs.length == 1);
 99                     nodes.put(fchar, fnode);
100                 } else {
101                     fnode = nodes.get(fchar);
102                     if (!fnode.isLast() && chs.length == 1)
103                         fnode.setLast(true);
104                 }
105                 lastIndex = chs.length - 1;
106                 for (int i = 1; i < chs.length; i++) {
107                     fnode = fnode.addIfNoExist(charConvert(chs[i]), i == lastIndex);
108                 }
109             }
110         }
111     }
112
113     /**
114      * 过滤判断 将敏感词转化为成屏蔽词
115      */
116     public static final String doFilter(final String src) {
117         char[] chs = src.toCharArray();
118         int length = chs.length;
119         int currc;
120         int k;
121         WordNode node;
122         for (int i = 0; i < length; i++) {
123             currc = charConvert(chs[i]);
124             if (!set.contains(currc)) {
125                 continue;
126             }
127             node = nodes.get(currc);
128             if (node == null)
129                 continue;
130             boolean couldMark = false;
131             int markNum = -1;
132             if (node.isLast()) {
133                 couldMark = true;
134                 markNum = 0;
135             }
136             k = i;
137             for (; ++k < length;) {
138                 int temp = charConvert(chs[k]);
139                 if (stopwdSet.contains(temp))
140                     continue;
141                 node = node.querySub(temp);
142                 if (node == null)
143                     break;
144                 if (node.isLast()) {
145                     couldMark = true;
146                     markNum = k - i;
147                 }
148             }
149             if (couldMark) {
150                 for (k = 0; k <= markNum; k++) {
151                     chs[k + i] = SIGN;
152                 }
153                 i = i + markNum;
154             }
155         }
156
157         return new String(chs);
158     }
159
160     /**
161      * 是否包含敏感词
162      */
163     public static final boolean isContains(final String src) {
164         char[] chs = src.toCharArray();
165         int length = chs.length;
166         int currc;
167         int k;
168         WordNode node;
169         for (int i = 0; i < length; i++) {
170             currc = charConvert(chs[i]);
171             if (!set.contains(currc)) {
172                 continue;
173             }
174             node = nodes.get(currc);
175             if (node == null)
176                 continue;
177             boolean couldMark = false;
178             if (node.isLast()) {
179                 couldMark = true;
180             }
181             k = i;
182             for (; ++k < length;) {
183                 int temp = charConvert(chs[k]);
184                 if (stopwdSet.contains(temp))
185                     continue;
186                 node = node.querySub(temp);
187                 if (node == null)
188                     break;
189                 if (node.isLast()) {
190                     couldMark = true;
191                 }
192             }
193             if (couldMark) {
194                 return true;
195             }
196         }
197
198         return false;
199     }
200
201     /**
202      * 大写转化为小写 全角转化为半角
203      */
204     private static int charConvert(char src) {
205         int r = BCConvert.qj2bj(src);
206         return (r >= 'A' && r <= 'Z') ? r + 32 : r;
207     }
208
209 }

WordFilter.java

其中:

isContains :是否包含敏感词

doFilter:过滤敏感词

2、WordNode敏感词节点:

 1 package com.skyer.sensitivewdfilter;
 2
 3 import java.util.LinkedList;
 4 import java.util.List;
 5
 6 public class WordNode {
 7
 8     private int value; // 节点名称
 9
10     private List<WordNode> subNodes; // 子节点
11
12     private boolean isLast; // 默认false
13
14     public WordNode(int value) {
15         this.value = value;
16     }
17
18     public WordNode(int value, boolean isLast) {
19         this.value = value;
20         this.isLast = isLast;
21     }
22
23     /**
24      * @return 就是传入的subNode
25      */
26     private WordNode addSubNode(final WordNode subNode) {
27         if (subNodes == null)
28             subNodes = new LinkedList<WordNode>();
29         subNodes.add(subNode);
30         return subNode;
31     }
32
33     /**
34      * 有就直接返回该子节点, 没有就创建添加并返回该子节点
35      */
36     public WordNode addIfNoExist(final int value, final boolean isLast) {
37         if (subNodes == null) {
38             return addSubNode(new WordNode(value, isLast));
39         }
40         for (WordNode subNode : subNodes) {
41             if (subNode.value == value) {
42                 if (!subNode.isLast && isLast)
43                     subNode.isLast = true;
44                 return subNode;
45             }
46         }
47         return addSubNode(new WordNode(value, isLast));
48     }
49
50     public WordNode querySub(final int value) {
51         if (subNodes == null) {
52             return null;
53         }
54         for (WordNode subNode : subNodes) {
55             if (subNode.value == value)
56                 return subNode;
57         }
58         return null;
59     }
60
61     public boolean isLast() {
62         return isLast;
63     }
64
65     public void setLast(boolean isLast) {
66         this.isLast = isLast;
67     }
68
69     @Override
70     public int hashCode() {
71         return value;
72     }
73
74 }

WordNode.java

3、测试类:

 1 package com.skyer.test;
 2
 3 import org.junit.Test;
 4
 5 import com.skyer.sensitivewdfilter.WordFilter;
 6
 7 public class TestSensitivewd {
 8
 9     @Test
10     public void TestFilter() {
11         String s = ""; // 这里写你要过滤的句子(我这里不能写,否则会给博客园屏蔽掉)
12         System.out.println("解析问题: " + s);
13         System.out.println("解析字数 : " + s.length());
14         String re;
15         long nano = System.nanoTime();
16         re = WordFilter.doFilter(s);
17         nano = (System.nanoTime() - nano);
18         System.out.println("解析时间 : " + nano + "ns");
19         System.out.println("解析时间 : " + nano / 1000000 + "ms");
20         System.out.println(re);
21         System.out.println();
22
23         nano = System.nanoTime();
24         System.out.println("是否包含敏感词: " + WordFilter.isContains(s));
25         nano = (System.nanoTime() - nano);
26         System.out.println("解析时间 : " + nano + "ns");
27         System.out.println("解析时间 : " + nano / 1000000 + "ms");
28     }
29
30 }

TestSensitivewd.java

4、测试结果:

原文参考:http://blog.csdn.net/fengshizty/article/details/52373005

DFA知识:http://www.cnblogs.com/naaoveGIS/archive/2016/10/14/5960352.html

转载于:https://www.cnblogs.com/Oven5217/p/6894695.html

使用DFA算法对敏感词进行过滤相关推荐

  1. java使用DFA算法实现敏感词过滤

    Java使用DFA算法实现敏感词过滤 DFA,全称 Deterministic Finite Automaton 即确定有穷自动机. 其特征为:有一个有限状态集合和一些从一个状态通向另一个状态的边,每 ...

  2. spring boot 使用DFA算法实现敏感词过滤

    spring boot 使用DFA算法实现敏感词过滤 敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的. DFA算法简介 DFA全称为:Deterministi ...

  3. 基于PHP的DFA算法(敏感词过滤)

    基于PHP的DFA算法(敏感词过滤) 看到网上很多的DFA算法,很多都有不同程度的问题,自己修改了一下,亲测没有问题,用在系统中过滤敏感词汇,比正则匹配的速度快很多. class DFA {priva ...

  4. 一种基于DFA算法的敏感词检测JAVA程序片段

    本文章提供一种基于DFA算法的敏感词检测JAVA程序片段,如下: 1.构造多叉树数据结构 import org.jetbrains.annotations.NotNull;/*** 多叉树* @aut ...

  5. java dfa 敏感词_java利用DFA算法实现敏感词过滤功能

    前言 敏感词过滤应该是不用给大家过多的解释吧?讲白了就是你在项目中输入某些字(比如输入xxoo相关的文字时)时要能检 测出来,很多项目中都会有一个敏感词管理模块,在敏感词管理模块中你可以加入敏感词,然 ...

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

    写项目时,得到一个新的需求,即实现敏感词的过滤,上网查了下,有几种实现方法,采取了DFA算法,即确定的有穷自动机算法,当初学习编译原理的时候为啥没想到DFA还能这么做,看来眼界和意识还是不够,得锻炼. ...

  7. dfa算法 java_Java实现DFA算法对敏感词、广告词过滤功能示例

    一.前言 开发中经常要处理用户一些文字的提交,所以涉及到了敏感词过滤的功能,参考资料中DFA有穷状态机算法的实现,创建有向图.完成了对敏感词.广告词的过滤,而且效率较好,所以分享一下. 具体实现: 1 ...

  8. DFA算法进行敏感词过滤

    1.新建敏感词文本new_adress.txt,进行添加敏感词 2.代码 # -*- coding:utf-8 -*- import timetime1 = time.time() "&qu ...

  9. 下发策略,DFA算法优化---敏感词查询

    1.定义 有穷自动机FA(Finite Automaton)的每一步操作都是确定的,因此可称为确定型有穷自动机.确定有穷自动机DFA(Deterministic Finite Automaton)就是 ...

  10. SpringBoot使用前缀树实现敏感词的过滤

    记录一下使用SpringBoot中使用前缀树对敏感词的一个过滤. 首先呢在resources目录下建立一个文件用来装敏感词例如我在resources/sensitive-words.txt如下: 敏感 ...

最新文章

  1. Windows系统盘符错乱导致桌面无法加载。
  2. php mysql简单留言本_php+mysql写的简单留言本实例代码
  3. MFC——文件打开和保存对话框(CFileDialog)
  4. electron 打包_Vue3+Electron整合方式
  5. Ansible无敌详细入门教程
  6. 左神算法进阶班5_3求公司的最大活跃度
  7. 用SSAS将多个FLV和MP3合成一个FLV文件
  8. 【Java】程序调试
  9. 单源最短路(spfa+Dijkstra)附数据
  10. 【linux】Redhat 7 更新 yum源
  11. c花体复制_能复制的花体英文字母
  12. 阅读ResNet论文 心得体会
  13. 写了四十篇办公自动化文章后,我整理了这十个常用操作,代码拿走就用!
  14. mysql经典sql语句大全_经典SQL语句大全(sql查询语句大全集锦)
  15. 这样的钓鱼邮件,你会中招吗?
  16. 一键重装系统win7教程
  17. c位边上还有什么位_章泽天聚会站边位,被称太委屈,看清C位的万宝宝后就明白了...
  18. Oracle对话框列间距太近,如何调整MathType矩阵行列间距
  19. Android桌面控件Widget解析
  20. Android手机静态ip地址网关,安卓手机Android 4.0系统静态ip设置方法【详解】

热门文章

  1. Zabbix系列:proxy存储数据表proxy_history
  2. 整合springmvc+mybatis+veloctiy二
  3. Zoomit的简单使用
  4. WP-南邮CTF逆向第三题 Py交易
  5. 8086CPU寄存器全称
  6. python实训报告万能模板_实训报告万能模板1000字
  7. 2022系统分析师--案例必备知识点汇总
  8. 学习记录2——PMSM数学建模——坐标变换理论以及相应的Matlab模块搭建
  9. 前端代码动态生成 审批流程图、流程图
  10. leetcode | 回文数