敏感词过滤算法DFA
生活随笔
收集整理的這篇文章主要介紹了
敏感词过滤算法DFA
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
DFA
敏感詞過濾方案
1 使用數據庫模糊查詢,效率太低
2 使用String.indexOf("")查找,數據庫量大的話也是比較慢
3 把敏感詞和內容使用全文檢索(solr,ElasticSearche)技術進行分詞再匹配,也是可以的,但是這種方案比較麻煩。
4 DFA算法,確定有窮自動機。本項目采用這種方案
DFA全稱為:Deterministic Finite Automaton,即確定有窮自動機。其特征為:有一個有限狀態集合和一些從一個狀態通向另一個狀態的邊,每條邊上標記有一個符號,其中一個狀態是初態,某些狀態是終態。但不同于不確定的有限自動機,DFA中不會有從同一狀態出發的兩條邊標志有相同的符號。
- 一次性的把所有的敏感詞存儲到了多個map中,就是下圖表示這種結構
敏感詞:冰毒、大麻、大壞蛋
- 檢索的過程,就是hashMap的get實現
1、第一個字“冰”,我們在hashMap中可以找到。得到一個新的map = hashMap.get("")。
2、如果map == null,則不是敏感詞。否則跳至3
3、獲取map中的isEnd,通過isEnd是否等于1來判斷該詞是否為最后一個。如果isEnd == 1表示該詞為敏感詞,否則跳至1。
通過這個步驟我們可以判斷“冰毒”為敏感詞,但是如果我們輸入“冰箱”則不是敏感詞了。
工具類:
import java.util.*;public class SensitiveWordUtil {public static Map<String, Object> dictionaryMap = new HashMap<>();/*** 生成關鍵詞字典庫* @param words* @return*/public static void initMap(Collection<String> words) {if (words == null) {System.out.println("敏感詞列表不能為空");return ;}// map初始長度words.size(),整個字典庫的入口字數(小于words.size(),因為不同的詞可能會有相同的首字)Map<String, Object> map = new HashMap<>(words.size());// 遍歷過程中當前層次的數據Map<String, Object> curMap = null;Iterator<String> iterator = words.iterator();while (iterator.hasNext()) {String word = iterator.next();curMap = map;int len = word.length();for (int i =0; i < len; i++) {// 遍歷每個詞的字String key = String.valueOf(word.charAt(i));// 當前字在當前層是否存在, 不存在則新建, 當前層數據指向下一個節點, 繼續判斷是否存在數據Map<String, Object> wordMap = (Map<String, Object>) curMap.get(key);if (wordMap == null) {// 每個節點存在兩個數據: 下一個節點和isEnd(是否結束標志)wordMap = new HashMap<>(2);wordMap.put("isEnd", "0");curMap.put(key, wordMap);}curMap = wordMap;// 如果當前字是詞的最后一個字,則將isEnd標志置1if (i == len -1) {curMap.put("isEnd", "1");}}}dictionaryMap = map;}/*** 搜索文本中某個文字是否匹配關鍵詞* @param text* @param beginIndex* @return*/private static int checkWord(String text, int beginIndex) {if (dictionaryMap == null) {throw new RuntimeException("字典不能為空");}boolean isEnd = false;int wordLength = 0;Map<String, Object> curMap = dictionaryMap;int len = text.length();// 從文本的第beginIndex開始匹配for (int i = beginIndex; i < len; i++) {String key = String.valueOf(text.charAt(i));// 獲取當前key的下一個節點curMap = (Map<String, Object>) curMap.get(key);if (curMap == null) {break;} else {wordLength ++;if ("1".equals(curMap.get("isEnd"))) {isEnd = true;}}}if (!isEnd) {wordLength = 0;}return wordLength;}/*** 獲取匹配的關鍵詞和命中次數* @param text* @return*/public static Map<String, Integer> matchWords(String text) {Map<String, Integer> wordMap = new HashMap<>();int len = text.length();for (int i = 0; i < len; i++) {int wordLength = checkWord(text, i);if (wordLength > 0) {String word = text.substring(i, i + wordLength);// 添加關鍵詞匹配次數if (wordMap.containsKey(word)) {wordMap.put(word, wordMap.get(word) + 1);} else {wordMap.put(word, 1);}i += wordLength - 1;}}return wordMap;}public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("冰毒");initMap(list);String content="我是一個好人,買賣冰毒是違法的";Map<String, Integer> map = matchWords(content);System.out.println(map);} }總結
以上是生活随笔為你收集整理的敏感词过滤算法DFA的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 让互联网助小组合作一臂之力
- 下一篇: 深入分析驴子系列(2)