日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java实现DFA算法敏感词过滤

發布時間:2023/12/20 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java实现DFA算法敏感词过滤 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java實現DFA算法敏感詞過濾。

文章目錄

  • 一. 應用場景
  • 二. 實現思路
  • 三. 源碼實現

一. 應用場景

模擬非法詞匯自動替換成*字符,且敏感詞匯支持動態調整。

效果如下,若配置了敏感詞:今天,則當用戶在輸入:今天,天氣真不錯。實際應該輸出:**,天氣真不錯

二. 實現思路

  • 使用MySQL作為敏感詞庫
  • 使用DFA算法實現文字過濾

Q:什么是DFA?

DFA全稱為:Deterministic Finite Automaton,即確定有窮自動機。其特征為:有一個有限狀態集合和一些從一個狀態通向另一個狀態的邊,每條邊上標記有一個符號,其中一個狀態是初態,某些狀態是終態。但不同于不確定的有限自動機,DFA中不會有從同一狀態出發的兩條邊標志有相同的符號。
確定:狀態以及引起狀態轉換的事件都是可確定的,不存在“意外”。
有窮:狀態以及事件的數量都是可窮舉的。

DFA算法模型如下:

state_event_dict = {"匹": {"配": {"算": {"法": {"is_end": True},"is_end": False},"關": {"鍵": {"詞": {"is_end": True},"is_end": False},"is_end": False},"is_end": False},"is_end": False},"信": {"息": {"抽": {"取": {"is_end": True},"is_end": False},"is_end": False},"is_end": False} }

用通俗易懂的話來解釋,就是將數據庫中的敏感詞進行建立樹結構,舉個例子,數據庫的敏感詞匯有三個,分別是:今天,今天很好,今天真煩。

建立樹結構,并且標記好三個詞匯的非葉子節點和葉子節點(即最后一個字符是葉子節點),并且制定好匹配規則,只有碰到葉子節點才算一次過濾:

模擬用戶輸入以下一句話:

我覺得今天還行。

接下來我們將這句話逐個字拆分并將每一個字代入到上面的樹狀結構圖中。

前面三個字不在敏感詞樹中直接可以跳過,直到遇到了這個字,發現匹配上了敏感詞樹,接下來看樹狀結構發現只有下一個字是才能被捕獲,繼續往下走果然發現這個字也匹配到了;

再接著走發現在樹結構中這個字的下一個字只有匹配到或者才能繼續匹配,而用戶輸入的下一個字是,第一步判斷當前已經走到了葉子節點,故先將今天置為敏感詞,然后將這個字從Top頂節點中重新繼續流轉,發現無法匹配。

過濾結束,且當前的節點是葉子節點,故這句話僅僅被敏感詞過濾了今天這兩個字,最終的過濾結果應該是:

我覺得**還行

要注意的是只有完整的碰到過一次葉子節點才算一次過濾,且一句話可以被多次過濾。以上就是針對DFA算法的簡單說明。

三. 源碼實現

理論知識加身,接下來就該實干了。Talk is cheap, show me the code:

import java.util.HashMap; import java.util.Map;/*** @author: Vainycos* @description 敏感字樹生成器* @date: 2021/12/4 12:45*/ public class TreeGenerator {/*** 將指定的詞分成字構建到一棵樹中。** @param tree* 字樹* @param sensitiveWord* 敏感詞詞* @return*/public static void addWord2Tree(Map<String, Map> tree, String sensitiveWord) {addWord2Tree(tree, sensitiveWord, 0);}private static Map<String, Map> addWord2Tree(Map<String, Map> tree,String word, int index) {if (index == word.length()) {tree.put(Finder.TREE_END_KEY, generateWordMap(word));return tree;}String next = word.substring(index, index + 1);Map<String, Map> subTree = tree.get(next);if (subTree == null) {subTree = new HashMap<String, Map>();}tree.put(next, addWord2Tree(subTree, word, index + 1));return tree;}private static Map<String, Object> generateWordMap(String word) {Map<String, Object> wordMap = new HashMap<String, Object>();wordMap.put(Finder.WORD_VALUE, word);wordMap.put(Finder.WORD_LENGTH, word.length());return wordMap;} } import lombok.extern.slf4j.Slf4j;import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap;/*** * 敏感詞過濾* */ @Slf4j @SuppressWarnings({ "rawtypes", "unchecked" }) public class Finder {// 敏感詞private static Set<String> WORDS = new HashSet<String>();// 由敏感詞生成的字樹private static Map<String, Map> TREE = new ConcurrentHashMap<String, Map>();// 默認敏感詞分割符public static final String DEFAULT_SEPARATOR = ",";/* 在樹當中標志一個詞的結束 */public static final String TREE_END_KEY = "^";// 敏感詞value標記public static final String WORD_VALUE = "v";// 敏感詞長度標記public static final String WORD_LENGTH = "l";// 默認替換符public static final char DEFAULT_REPLACEMENT = '*';// 默認起始標記public static final String DEFAULT_START_TAG = "<font color=\"red\">";// 默認結束標記public static final String DEFAULT_END_TAG = "</font>";public Finder(String[] words) {addSensitiveWords(words);}/*** 刪除所有敏感詞*/public static void clearSensitiveWords() {WORDS.clear();TREE.clear();}/*** * 添加敏感詞* * @author hymer* @param words*/public static void addSensitiveWords(String[] words) {if (words == null || words.length == 0) {return;}check(words);addWords(words);}/*** * 添加敏感詞* * @author hymer* @param words* @param separator*/public static void addSensitiveWords(String words, String separator) {if (words != null && !"".equals(words.trim())) {check(words);String[] sensitiveWords = words.split(separator);addWords(sensitiveWords);}}/*** * 添加敏感詞,默認使用,分割* * @author hymer* @param words*/public static void addSensitiveWords(String words) {check(words);addSensitiveWords(words, DEFAULT_SEPARATOR);}/*** 刪除敏感詞* * @param words*/public static void removeSensitiveWords(String words) {check(words);removeSensitiveWords(words, DEFAULT_SEPARATOR);}/*** 刪除敏感詞* * @param words*/public static void removeSensitiveWords(String words, String separator) {if (words != null && !"".equals(words.trim())) {check(words);String[] sensitiveWords = words.split(separator);removeWords(sensitiveWords);}}/*** 刪除敏感詞* * @param words*/public static void removeSensitiveWords(String[] words) {if (words == null || words.length == 0) {return;}check(words);removeWords(words);}/*** * 找出文本中的敏感詞* * @author hymer* @param text* @return*/public static Set<String> find(String text) {return new TextAnalysis().analysis(TREE, text);}/*** 替換文本中的敏感詞* * @param text* 含敏感詞的文本* @return*/public static String replace(String text) {return new TextAnalysis().replace(TREE, text, DEFAULT_REPLACEMENT);}/*** 替換文本中的敏感詞* * @param text* 含敏感詞的文本* @param replacement* 替換字符* @return*/public static String replace(String text, Character replacement) {return new TextAnalysis().replace(TREE, text, replacement);}/*** * 過濾文本,并標記出敏感詞,默認使用HTML中紅色font標記* * @author hymer* @param text* @return*/public static String filter(String text) {return new TextAnalysis().mark(TREE, text, DEFAULT_START_TAG, DEFAULT_END_TAG);}/*** * 過濾文本,并標記出敏感詞* * @author hymer* @param text* @param startTag* @param endTag* @return*/public static String filter(String text, String startTag, String endTag) {return new TextAnalysis().mark(TREE, text, startTag, endTag);}private static void check(String... words) {for (String word : words) {if (word != null && word.contains(TREE_END_KEY)) {throw new RuntimeException("包含非法字符:" + TREE_END_KEY);}}}private static void addWords(String... sensitiveWords) {for (String word : sensitiveWords) {if (word != null && !word.trim().equals("")) {word = word.trim();int len = word.length();if (len > 1024) {throw new RuntimeException("敏感詞太長[最長1024]!");}// 添加該詞,如果未重復,則添加到treeif (WORDS.add(word)) {TreeGenerator.addWord2Tree(TREE, word);}}}log.info("當前敏感詞數量:", WORDS.size());}private static void removeWords(String... sensitiveWords) {for (String word : sensitiveWords) {if (word != null && !word.trim().equals("")) {word = word.trim();WORDS.remove(word);}}TREE.clear();addWords(WORDS.toArray(new String[WORDS.size()]));}@SuppressWarnings("unused")private static void printTree(Map<String, Map> wordTree, int level) {if (wordTree == null || wordTree.isEmpty()) {return;}Iterator<String> it = wordTree.keySet().iterator();while (it.hasNext()) {String next = it.next();Object tmp = wordTree.get(next);if (tmp instanceof Map) {printTree((Map) tmp, level + 1);}}}}

以上就是關鍵代碼,接下來我們測試一下效果:

public static void main(String[] args) {String content = "我覺得今天還行。";// 定義敏感詞庫 后續可以對接數據庫String[] sensitiveWords = {"今天", "今天很好", "今天真煩"};// 設置敏感詞庫Finder.addSensitiveWords(sensitiveWords);// 敏感詞過濾替換字符為*String replace = Finder.replace(content, '*');// 輸出結果:我覺得**還行。System.out.println(replace); }

發現效果還不錯。至此,一個簡單的DFA算法實現敏感詞過濾功能就實現了。

參考資料:

  • Java實現敏感詞過濾
  • java 敏感詞工具實現思路
  • 參考實現代碼

總結

以上是生活随笔為你收集整理的Java实现DFA算法敏感词过滤的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。