在csdn上看到一篇DFA算法替换敏感词的全文替换文章,同时也看到网上不少文章说对于这种敏感词功能替换无疑DFA是一种效率不错的实现。
下面是基本FDA实现的java代码
public class DFA { private Node rootNode = new Node('R'); private int a = 0; private StringBuilder strWord = new StringBuilder(); public void searchWord(String content) { char[] chars =content.toCharArray(); Node node = rootNode; while(a<chars.length) { node = findNode(node,chars[a]); if(node == null){ node = rootNode; strWord.append(chars[a]); }else{ strWord.append("*"); } a++; } } public void createTree() { for(String str : arr) { char[] chars = str.toCharArray(); if(chars.length > 0) insertNode(rootNode, chars, 0); } } private void insertNode(Node node, char[] cs, int index) { Node n = findNode(node, cs[index]); if(n == null) { n = new Node(cs[index]); node.nodes.add(n); } if(index == (cs.length-1)) n.flag = 1; index++; if(index<cs.length) insertNode(n, cs, index); } private Node findNode(Node node, char c) { List<Node> nodes = node.nodes; Node rn = null; for(Node n : nodes) { if(n.c==c) { rn = n; break; } } return rn; } private static class Node { public char c; public int flag; //1:表示终结,0:延续 这里只替换成*所以用不着 public List<Node> nodes = new ArrayList<Node>(); public Node(char c) { this.c = c; this.flag = 0; } public Node(char c, int flag) { this.c = c; this.flag = flag; } } }
下面是自己写的用Map实现的一段替换代码
public String replaceAllWord(String[] arr,String content){
char conCharArry[] = content.toCharArray();
//这里key为每个敏感词的第一个字符,里面放着第一个字符相同的敏感词list集合
Map<Character, List<String>> word = new HashMap<Character, List<String>>();
//遍历数组生成敏感词map对象
for(String str : arr){
char key = str.charAt(0);
List<String> list = word.get(key);
if(list == null){
list = new ArrayList<String>();
list.add(str);
word.put(key, list);
}else{
list.add(str);
}
}
//对内容每一个字符进行遍历,如果当前字符为敏感词的首字符则进行下面行为否则continue本次操作
for(int i = 0 ; i < conCharArry.length; i++){
List<String> list = word.get(conCharArry[i]);
if(list == null){
continue;
}
for(String str : list){
char words[] = str.toCharArray();
//对是否匹配一个完整的敏感词进行标志,如果匹配敏感词过程中有一个字符不符则标注为false
boolean mark = true;
for(int j = 0; j < words.length; j++){
if(j + i <= conCharArry.length && words[j] != conCharArry[j+i]){
mark = false;
break;
}
}
//把敏感词逐个替换成*
if(mark){
for(int j = 0; j < words.length; j++){
conCharArry[i++] = '*';
}
}
}
}
return new String(conCharArry);
}
当我们在main函数中测试代码
public static void main(String[] args) { String[] arr = {"tmd", "小姐", "DA"}; String content = "tmd ITeye文章版权属于作者,受法律保护 Da 小姐" long start = System.currentTimeMillis(); for(int i = 0; i < 10000 ; i++){ DFA dfa = new DFA(); dfa.createTree(arr ); dfa.searchWord(); //dfa.replaseAllword(arr,content); } long end =System.currentTimeMillis(); System.out.println(end - start); }
测试结果
DFA实现:45毫秒
Map实现:16毫秒
当把替换类型加至11220字、敏感字词数组增至十来个时
DFA实现:16903毫秒
Map实现:4758毫秒
这里DFA效率不如下面的hash实现的疑惑还请各位指点下。
ps:
加一段备用修改后的代码(properties配制)
@SuppressWarnings("unchecked") public String replaceWordStr(String content) { char conCharArry[] = content.toCharArray(); StringBuffer sb = new StringBuffer(); // 这里key为每个敏感词的第一个字符,里面放着第一个字符相同的敏感词list集合 Map<Character, List<String>> word = new HashMap<Character, List<String>>(); // 遍历数组生成敏感词map对象 for (Entry entry : properties.entrySet()) { String keyWrod = entry.getKey().toString(); char key = "".equals(keyWrod) ? ' ' : keyWrod.charAt(0); List<String> list = word.get(key); if (list == null) { list = new ArrayList<String>(); list.add(keyWrod); word.put(key, list); } else { list.add(keyWrod); } } // 对内容每一个字符进行遍历,如果当前字符为敏感词的首字符则进行下面行为否则continue本次操作 for (int i = 0; i < conCharArry.length; i++) { List<String> list = word.get(conCharArry[i]); if (list == null) { sb.append(conCharArry[i]); continue; } for (String str : list) { char words[] = str.toCharArray(); // 对是否匹配一个完整的敏感词进行标志,如果匹配敏感词过程中有一个字符不符则标注为false boolean mark = true; for (int j = 0; j < words.length; j++) { if (j + i <= conCharArry.length && words[j] != conCharArry[j + i]) { mark = false; break; } } // 把敏感词逐个替换 if (mark) { sb.append(properties.get(str)); for (int j = 1; j < words.length; j++) { i++; } } else { sb.append(conCharArry[i]); } } } return sb.toString(); }
相关推荐
算法思路:把敏感词的第一个字符取出来,作为比较对象。遍历整个字符串,如果发现字符跟敏感词第一个字符相同,就从字符串取出跟关键词相同长度的子串比较,如果相同就替换。本算法比较适合敏感词都不长的场合。
高效敏感词过滤JAVA实现(DFA算法) 5000字2ms 节点 + 2进制标识(节省空间/提高查询效率) 附源码、注释,附带专业敏感词库(3396个敏感词) 看得上就拿去用,替换下一两处util方法、改个路径即可 不求什么,...
基于单模式串和 Trie 树实现的敏感词过滤我们前面几节讲了好几种字符串匹配算法,有 BF 算法、RK 算法、BM 算法、KMP 算法,前面四种算法都是单模式串
高效敏感词过滤JAVA实现(DFA算法) 5000字2ms 节点 + 2进制标识(节省空间/提高查询效率) 附源码、注释,附带专业敏感词库(3396个敏感词) 看得上就拿去用,替换下一两处util方法、改个路径即可 不求什么,...
基于KMP算法的字符替换,选择读取文件 ,然后进行字符替换
文件删除 当目录不存在时创建目录 将xml转存为ArrayList 敏感词检查 敏感词替换
java编写的匹配关键字,并替换关键字,提供关键字设置,替换敏感词 java编写的匹配关键字,并替换关键字,提供关键字设置,替换敏感词 java编写的匹配关键字,并替换关键字,提供关键字设置,替换敏感词 java编写的...
该项目作为一个敏感词检测工具,具有敏感词获取、敏感词处理、敏感词替换等基本功能,还支持用户自己实现对应的敏感词获取器 和 敏感词解析器实现一些自定义的功能。 实现原理 底层的实现原理采取的是AC自动机...
在Filter 过滤器中,我们先拿到用户提交的留言,如果出现了敏感词,我们就用*号来替换。----------------------------------------------- 通过Filter来实现留言板的敏感词过滤... 思路很简单,我们这里的敏感词是...
word源码java copyright 不管您是个人还是公司都可以随意使用DzFilter,并且随意修改源代码。感谢大家的使用! 温馨提示 用于生产环境时请替换项目的数据库连接代码,使用数据连接池的方式操作数据库!非常抱歉,本...
idea+maven+proguard,通过proguard实现源码的混淆编译,将源码的原始变量、方法名等按proguard规则进行统一修改替换,保证功能不变的情况下,一定程度提高源码的安全性,避免源码中的敏感词变量引起的安全检查异常...
MsgProcessor是消息管理类,setMsg方法设置消息字符串。HTMLFilter的功能是将尖括号替换成中括号;SesitiveFilter的功能是将消息中的敏感词过滤掉;FaceFilter的功能是将笑脸替换成另一种表情符号。
多模式匹配(替换)具有很强的现实意义与实用价值:敏感词过滤,病毒特征码搜索等。 字典中约有一千条关键字,分为三大类:电影、音乐、电影&音乐,将输入文本中的字典记录替换为相应的类别文本。遵循贪婪原则与最先...
敏感词是对文档内容中某些国家或法律禁止的词汇、不文明词汇(如操、他妈的等)进行自动替换,前台网友阅读文档时看到个词语将会被替换成别的字符,如“***”,在大型门户里面经常能看到这种功能。点击“数据中心”...
敏感词过滤 直接从Java版DFA算法实现,转移过来,并未作修改,词库直接从百度搜索的一个暂用。 可替换成其他词库,也可自行添加词条。 在项目init方法中调用ReadSwfDict加载词库 在检查点调用Match方验证,或调用...
JTopcms基于J2EE核心模式自主研发,立项之初即考虑二次开发支持,扩展新模块只需具备Java web开发基础以及SQL能力,就可快速上手,高效无侵入方式开发功能。 11.支持资源发布点 支持自动将图片 视频 文件 以及静态...
MySQL5.5或更高版本(如需使用MySQL5.0,可将mysql驱动版本替换为5.1.24)。如何连接MySQL8数据库 浏览器:IE11、Edge、Firefox、Chrome。 Kotlin1.3或更高版本。(开发环境需要) Maven3.3或更高版本。(开发...
JTopcms基于J2EE核心模式自主研发,立项之初即考虑二次开发支持,扩展新模块只需具备Java web开发基础以及SQL能力,就可快速上手,高效无侵入方式开发功能。 11.支持资源发布点 支持自动将图片 视频 文件 以及静态...