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敏感词用拼音或部分用拼音代替

两种解决思路:一种是最简单是遇到这类问题,先丰富敏感词库进行快速解决。第二种是判断时将敏感词转换为拼音进行对比判断。

不过目前这两种方案均不能彻底很好的解决该问题,此类问题还需进一步研究。

 

posted @ 2019-03-13 15:51  长途跋涉的孤狼  阅读(1710)  评论(0编辑  收藏  举报