使用DFA算法对敏感词进行过滤
项目目录结构如下:
其中resources资源目录中:
stopwd.txt :停顿词,匹配时间直接过滤。
wd.txt:敏感词库。
1、WordFilter敏感词过滤类:
package com.skyer.sensitivewdfilter; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * 思路: 创建一个FilterSet,枚举了0~65535的所有char是否是某个敏感词开头的状态 * * 判断是否是 敏感词开头 | | 是 不是 获取头节点 OK--下一个字 然后逐级遍历,DFA算法 */ public class WordFilter { private static final FilterSet set = new FilterSet(); // 存储首字 private static final Map<Integer, WordNode> nodes = new HashMap<Integer, WordNode>(1024, 1); // 存储节点 private static final Set<Integer> stopwdSet = new HashSet<Integer>(); // 停顿词 private static final char SIGN = '*'; // 敏感词过滤替换 static { try { long a = System.nanoTime(); init(); a = System.nanoTime() - a; System.out.println("加载时间 : " + a + "ns"); System.out.println("加载时间 : " + a / 1000000 + "ms"); } catch (Exception e) { throw new RuntimeException("初始化过滤器失败"); } } private static void init() { // 获取敏感词 addSensitiveWord(readWordFromFile("wd.txt")); addStopWord(readWordFromFile("stopwd.txt")); } /** * 增加敏感词 */ private static List<String> readWordFromFile(String path) { List<String> words; BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(WordFilter.class.getClassLoader().getResourceAsStream(path))); words = new ArrayList<String>(1200); for (String buf = ""; (buf = br.readLine()) != null;) { if (buf == null || buf.trim().equals("")) continue; words.add(buf); } } catch (Exception e) { throw new RuntimeException(e); } finally { try { if (br != null) br.close(); } catch (IOException e) { } } return words; } /** * 增加停顿词 */ private static void addStopWord(final List<String> words) { if (words != null && words.size() > 0) { char[] chs; for (String curr : words) { chs = curr.toCharArray(); for (char c : chs) { stopwdSet.add(charConvert(c)); } } } } /** * 添加DFA节点 */ private static void addSensitiveWord(final List<String> words) { if (words != null && words.size() > 0) { char[] chs; int fchar; int lastIndex; WordNode fnode; // 首字母节点 for (String curr : words) { chs = curr.toCharArray(); fchar = charConvert(chs[0]); if (!set.contains(fchar)) {// 没有首字定义 set.add(fchar);// 首字标志位 可重复add fnode = new WordNode(fchar, chs.length == 1); nodes.put(fchar, fnode); } else { fnode = nodes.get(fchar); if (!fnode.isLast() && chs.length == 1) fnode.setLast(true); } lastIndex = chs.length - 1; for (int i = 1; i < chs.length; i++) { fnode = fnode.addIfNoExist(charConvert(chs[i]), i == lastIndex); } } } } /** * 过滤判断 将敏感词转化为成屏蔽词 */ public static final String doFilter(final String src) { char[] chs = src.toCharArray(); int length = chs.length; int currc; int k; WordNode node; for (int i = 0; i < length; i++) { currc = charConvert(chs[i]); if (!set.contains(currc)) { continue; } node = nodes.get(currc); if (node == null) continue; boolean couldMark = false; int markNum = -1; if (node.isLast()) { couldMark = true; markNum = 0; } k = i; for (; ++k < length;) { int temp = charConvert(chs[k]); if (stopwdSet.contains(temp)) continue; node = node.querySub(temp); if (node == null) break; if (node.isLast()) { couldMark = true; markNum = k - i; } } if (couldMark) { for (k = 0; k <= markNum; k++) { chs[k + i] = SIGN; } i = i + markNum; } } return new String(chs); } /** * 是否包含敏感词 */ public static final boolean isContains(final String src) { char[] chs = src.toCharArray(); int length = chs.length; int currc; int k; WordNode node; for (int i = 0; i < length; i++) { currc = charConvert(chs[i]); if (!set.contains(currc)) { continue; } node = nodes.get(currc); if (node == null) continue; boolean couldMark = false; if (node.isLast()) { couldMark = true; } k = i; for (; ++k < length;) { int temp = charConvert(chs[k]); if (stopwdSet.contains(temp)) continue; node = node.querySub(temp); if (node == null) break; if (node.isLast()) { couldMark = true; } } if (couldMark) { return true; } } return false; } /** * 大写转化为小写 全角转化为半角 */ private static int charConvert(char src) { int r = BCConvert.qj2bj(src); return (r >= 'A' && r <= 'Z') ? r + 32 : r; } }
WordFilter.java
其中:
isContains :是否包含敏感词
doFilter:过滤敏感词
2、WordNode敏感词节点:
package com.skyer.sensitivewdfilter; import java.util.LinkedList; import java.util.List; public class WordNode { private int value; // 节点名称 private List<WordNode> subNodes; // 子节点 private boolean isLast; // 默认false public WordNode(int value) { this.value = value; } public WordNode(int value, boolean isLast) { this.value = value; this.isLast = isLast; } /** * @return 就是传入的subNode */ private WordNode addSubNode(final WordNode subNode) { if (subNodes == null) subNodes = new LinkedList<WordNode>(); subNodes.add(subNode); return subNode; } /** * 有就直接返回该子节点, 没有就创建添加并返回该子节点 */ public WordNode addIfNoExist(final int value, final boolean isLast) { if (subNodes == null) { return addSubNode(new WordNode(value, isLast)); } for (WordNode subNode : subNodes) { if (subNode.value == value) { if (!subNode.isLast && isLast) subNode.isLast = true; return subNode; } } return addSubNode(new WordNode(value, isLast)); } public WordNode querySub(final int value) { if (subNodes == null) { return null; } for (WordNode subNode : subNodes) { if (subNode.value == value) return subNode; } return null; } public boolean isLast() { return isLast; } public void setLast(boolean isLast) { this.isLast = isLast; } @Override public int hashCode() { return value; } }
WordNode.java
3、测试类:
package com.skyer.test; import org.junit.Test; import com.skyer.sensitivewdfilter.WordFilter; public class TestSensitivewd { @Test public void TestFilter() { String s = ""; // 这里写你要过滤的句子(我这里不能写,否则会给博客园屏蔽掉) System.out.println("解析问题: " + s); System.out.println("解析字数 : " + s.length()); String re; long nano = System.nanoTime(); re = WordFilter.doFilter(s); nano = (System.nanoTime() - nano); System.out.println("解析时间 : " + nano + "ns"); System.out.println("解析时间 : " + nano / 1000000 + "ms"); System.out.println(re); System.out.println(); nano = System.nanoTime(); System.out.println("是否包含敏感词: " + WordFilter.isContains(s)); nano = (System.nanoTime() - nano); System.out.println("解析时间 : " + nano + "ns"); System.out.println("解析时间 : " + nano / 1000000 + "ms"); } }
TestSensitivewd.java
4、测试结果:
原文参考:http://blog.csdn.net/fengshizty/article/details/52373005
DFA知识:http://www.cnblogs.com/naaoveGIS/archive/2016/10/14/5960352.html
使用DFA算法对敏感词进行过滤的更多相关文章
- DFA算法实现敏感词过滤
DFA算法:即确定有穷自动机,简单点说就是,它是是通过event和当前的state得到下一个state,即event+state=nextstate.理解为系统中有多个节点,通过传递进入的event, ...
- Java 利用DFA算法 屏蔽敏感词
原文:http://www.open-open.com/code/view/1435214601278 import java.io.BufferedReader; import java.io.Fi ...
- 如何用Python实现敏感词的过滤
题目要求如下: 从文件解析敏感词,从终端获取用户输入.根据敏感词对用户输入进行过滤.这里过滤需要考虑不止一个过滤词:即将读取的所有过滤词,放进一个列表,用屏蔽词检索用户输入,如果有屏蔽词,则将其替换为 ...
- Java实现敏感词过滤 - DFA算法
Java实现DFA算法进行敏感词过滤 封装工具类如下: 使用前需对敏感词库进行初始化: SensitiveWordUtil.init(sensitiveWordSet); package cn.swf ...
- 敏感词过滤的算法原理之DFA算法
参考文档 http://blog.csdn.net/chenssy/article/details/26961957 敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有 ...
- DFA和trie特里实现敏感词过滤(python和c语言)
今天的项目是与完成python开展,需要使用做关键词检查,筛选分类,使用前c语言做这种事情.有了线索,非常高效,内存小了,检查快. 到达python在,第一个想法是pip基于外观的c语言python特 ...
- Java实现敏感词过滤
敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来 ...
- Java实现敏感词过滤(转)
敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来 ...
- Jsp敏感词过滤
Jsp敏感词过滤 大部分论坛.网站等,为了方便管理,都进行了关于敏感词的设定. 在多数网站,敏感词一般是指带有敏感政治倾向(或反执政党倾向).暴力倾向.不健康色彩的词或不文明语,也有一些网站根据自身实 ...
随机推荐
- 老李推荐:第14章1节《MonkeyRunner源码剖析》 HierarchyViewer实现原理-面向控件编程VS面向坐标编程
老李推荐:第14章1节<MonkeyRunner源码剖析> HierarchyViewer实现原理-面向控件编程VS面向坐标编程 poptest是国内唯一一家培养测试开发工程师的培训机 ...
- hibernate的反转引擎生成两个实体类的问题
在使用myeclipse中自带的hibernate 进行jsp开发时候遇到了这个问题.使用hibernate的反转引擎从数据库生成生成实体类,一个表生成了两个类,xx.java和xxId.java . ...
- 发散问题——Spring容器及加载
一.前言 发散问题系列,是围绕日常工作,发散思考,提取问题,并寻求答案的一个系列.总的来说,就是将遇到的问题发散来提出更多的问题,并通过解决发散问题,从而对问题有更深入的了解,对知识有更深刻的记忆,帮 ...
- 前端代码组织优化--小demo(进阶你的思路)
事出必有因 最近在看老项目的代码,一个富客户端的js代码,几千行的代码,全是function(){} var...的垂直布局,真的是要感动的哭了. 一开始都是这样,想实现什么功能,不管三七二十一,fu ...
- 图解函数重载以及arguments
- Mac OS平台下应用程序安装包制作工具Packages的使用介绍(补充)
上一篇:Mac OS平台下应用程序安装包制作工具Packages的使用介绍 补充说明 上一篇文章中介绍了如何使用Packages如何创建mac下的安装包.但是这样制作出来的安装包只能安装到系统的文件路 ...
- 怎么看iOS human interface guidelines中的user control原则
最近离开了老东家,整理整理思路,因为一直做的是微信公众号相关的产品对app的东西有一段时间没有做过了,所以又看了一遍iOS human interface guidelines,看到user cont ...
- 【PAT_Basic日记】1001. 害死人不偿命的(3n+1)猜想
还是觉得代码放这靠谱,会定期的看看和优化代码 #include <stdio.h> #include <stdlib.h> int main() { int n; int co ...
- C# treeview 使用笔记
treeView默认 展开 treeView1.ExpandAll(); treeview判断点击节点: private void treeView1_AfterSelect(object sende ...
- STM32学习笔记(四)——串口控制LED(中断方式)
目录: 一.时钟使能,包括GPIO的时钟和串口的时钟使能 二.设置引脚复用映射 三.GPIO的初始化配置,注意要设置为复用模式 四.串口参数初始化配置 五.中断分组和中断优先级配置 六.设置串口中断类 ...