DFA算法
今天新学习了一个敏感词匹配的算法,记录一下。
原文地址:https://blog.csdn.net/qq_36827957/article/details/74357283
1、用途:
DFA算法又称为有穷状态机,主要用于敏感词匹配。
2、原理:
以王八蛋和王八羔子两个敏感词来进行描述,首先构建敏感词库,该词库名称为SensitiveMap,这两个词的二叉树构造为:
以上面例子构造出来的SensitiveMap为敏感词库进行示意,假设这里输入的关键字为:王八不好,流程图如下:
3.代码编写
3.1构造敏感词实现代码
@SuppressWarnings({ "rawtypes", "unchecked" }) public void addSensitveWord(Set<String> words){ sensitiveWordMap = new HashMap(words.size()); Map nowMap = null; Map newWordMap = null; for(String word : words){ nowMap = sensitiveWordMap;// 指向知道集合的头部,初始位置。 for(int i =0; i < word.length(); i++){ char keyChar = word.charAt(i); Object wordMap = nowMap.get(keyChar); if(wordMap != null){ nowMap = (Map)wordMap;//将指向移动到此keyChar存在的位置。 }else{ newWordMap = new HashMap<String, String>(); newWordMap.put("isEnd", "0"); nowMap.put(keyChar, newWordMap); nowMap = newWordMap; //将指向移动到下一个字符 } if(i == word.length() - 1){ nowMap.put("isENd", "1"); } } } }
3.2实现敏感词查询代码
@SuppressWarnings("rawtypes") public int checkSensitiveWord(String txt, int beginIndex){ boolean flag = false; int matchFlag = 0; char word = 0; Map nowMap = sensitiveWordMap; for(int i = beginIndex; i < txt.length(); i++){ word = txt.charAt(i); nowMap = (Map) nowMap.get(word); if(nowMap != null){ matchFlag++; if("1".equals(nowMap.get("isEnd"))){ flag = true; } }else{ break; } } //如果只匹配了一个词,则不认为是敏感词 if(matchFlag < 2 || !flag){ matchFlag = 0; } return matchFlag; }
4.优化思路
4.1敏感词中间填充无意义字符问题
对于“王*八&&蛋”这样的词,中间填充了无意义的字符来混淆,在我们做敏感词搜索时,同样应该做一个无意义词的过滤,当循环到这类无意义的字符时进行跳过,避免干扰。
4.2敏感词用拼音或部分用拼音代替
两种解决思路:一种是最简单是遇到这类问题,先丰富敏感词库进行快速解决。第二种是判断时将敏感词转换为拼音进行对比判断。
不过目前这两种方案均不能彻底很好的解决该问题,此类问题还需进一步研究。