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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DFA敏感词过滤算法详解

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

功能簡介

DFA算法模型是解決針對一段文本,過濾出其他文本。比如我們定義了三段文本a、b和c為“張三”、“程序員”、“開發”,而在文本d“我的名字叫張三,我是一名剛工作一年的程序員”的內容中,可以發現文本d是包含a和b文本的,這個過程就是DFA算法模型實現的功能。DFA算法的核心是構建出一個模型。

拋出疑問

  • java中有contain方法進行判斷a文本是否包含b文本,為什么不直接用contain進行比較呢?
  • DFA算法用Java如何構建?
  • DFA算法性能如何?
  • 算法思想

    舉個例子,假如我們認為以下是敏感詞。

    1. 我是張三2. 我是李四3. 大王八4. 大王來了

    然后我們根據上面的敏感詞構建出一個模型,該模型實際上是一顆樹,或者說是森林。在java代碼中實際上是多個map,為了方便觀察,我轉換成了json。(不完整版本)

    {"我": {"是": {"張": {"三": {}},"李": {"四": {}}}},"大": {"王": {"來": {"了": {}},"八": {}}}}

    我們通過上面構建的模型對目標文本“我是張三,我是大王”進行敏感詞過濾,大致過程如下:

    1. 遍歷目標文本,獲取到第一個字符‘我’,在我們構建的模型的第一層比較,發現第一層的字符串是‘我’和‘大’。 2. 字符‘我’能夠在模型中匹配到,繼續獲取目標文本的下一個字符‘是’,發現第二層也是‘是’,也是匹配上了,依次是‘張’、‘三’。 3. 通過步驟2我們可以斷定目標文本中“我是張三”是敏感詞,記錄下來。 4. 繼續獲取下一個字符,這里節省時間直接跳到‘大’的字符,發現可以和第一層的‘大’匹配上,然后獲取目標文本中的下一個字符‘王’,也能夠在模型中匹配上。 5. 這樣整個匹配過程完成了,大家可能有疑問,那到底“大王”算不算敏感詞呢?如果算,但是我們在定義敏感詞的時候并沒有“大王”;如果不算,但確實是匹配上了。

    為了解決這個問題,我們在構建好的模型中加一個字段就可以解決這種摸棱兩可的問題。

    {"我": {"isEnd": false,"是": {"張": {"三": {"isEnd": true},"isEnd": false},"isEnd": false,"李": {"四": {"isEnd": true},"isEnd": false}}},"大": {"王": {"來": {"了": {"isEnd": true},"isEnd": false},"八": {"isEnd": true},"isEnd": false},"isEnd": false}}

    可以看到加了一個isEnd字段進行記錄構建的模型,每段敏感詞的結尾是true,如果不是結尾則是false,比如“我”“我是”“我是張”都為false,而“我是張三”為true。通過這個字段每次來判斷敏感詞校驗是否到了敏感詞的結尾。
    回到上面的問題:“大王”到底算不算敏感詞呢?
    根據上面的分析,只有完整匹配上模型中的敏感詞才能算敏感詞,所以在比較‘王’的時候發現isEnd是false,說明“大王”只是“大王八”或者“大王來了”的一部分,并不能算敏感詞。所以目標文本“我是張三,我是大王”中“我是張三”是敏感詞,“大王”不是敏感詞。

    構建DFA模型

    下面用java代碼構建一個DFA模型

    /*** @param keyWordSet 敏感詞庫*/private Map addSensitiveWordToHashMap(Set<String> keyWordSet) {// 初始化敏感詞容器,減少擴容操作Map sensitiveWordMap = new HashMap(keyWordSet.size());String key;Map nowMap;Map<String, String> newWordMap;// 遍歷keyWordSetfor (String aKeyWordSet : keyWordSet) {// 關鍵字key = aKeyWordSet;nowMap = sensitiveWordMap;for (int i = 0; i < key.length(); i++) {// 轉換成char型char keyChar = key.charAt(i);// 65279是一個空格,遇到空格直接跳過即可if ((int) keyChar == 65279) {continue;}// 獲取Object wordMap = nowMap.get(keyChar);if (wordMap != null) {// 如果存在該key,直接賦值nowMap = (Map) wordMap;} else {// 不存在則,則構建一個map,同時將isEnd設置為0,因為他不是最后一個newWordMap = new HashMap<>();// 不是最后一個newWordMap.put("isEnd", "0");nowMap.put(keyChar, newWordMap);nowMap = newWordMap;}if (i == key.length() - 1) {// 最后一個nowMap.put("isEnd", "1");}}}return sensitiveWordMap;}

    構建好模型之后,通過下面方法進行判斷是否存在敏感詞。

    /*** 過濾出敏感詞** @param txt 目標文本* @param matchType 匹配模式 1、最小匹配模式 2、最大匹配模式*/ public Set<String> getSensitiveWordSets(String txt, int matchType) {Set<String> sensitiveWordSets = new HashSet<>();for (int n = 0; n < txt.length(); n++) {// 判斷是否包含敏感字符int length = judgeSensitiveWithIndex(txt, n, matchType);if (length > 0) {// 存在,加入list中sensitiveWordSets.add(txt.substring(n, n + length));// 減1的原因,是因為for會自增n = n + length - 1;}}return sensitiveWordSets;}/*** 根據指定位置是否是敏感詞的開始** @param txt 文本* @param beginIndex 開始位置* @param matchType 匹配模式 1、最小匹配模式 2、最大匹配模式* @return int*/private int judgeSensitiveWithIndex(String txt, int beginIndex, int matchType) {// 匹配標識數默認為0int matchFlag = 0;char word;boolean isEnd = false;Map nowMap = sensitiveWordMap;for (int i = beginIndex; i < txt.length(); i++) {word = txt.charAt(i);// 獲取指定keynowMap = (Map) nowMap.get(word);// 存在,則判斷是否為最后一個if (nowMap != null) {// 找到相應key,匹配標識+1matchFlag++;if ((boolean) nowMap.get("isEnd")) {// 如果為最后一個匹配規則,結束循環,返回匹配標識數isEnd = true;break;}} else {// 不存在,直接返回break;}}if (1 == matchType) {// 最小匹配模式return matchFlag;}// 最大匹配模式if (isEnd) {return matchFlag;}return 0;}

    解答疑問

    1. java中有contain方法進行判斷a文本是否包含b文本,為什么不直接用contain進行比較呢?
    可以從兩方面考慮:
    功能方面,contain只能進行最大匹配模式進行匹配,比如目標文本“我是張三,我是大王”,針對敏感詞“大王八”,目標文本中的“大王”正常來說是不算敏感詞的,但是要是有這么個需求就認為“大王”是敏感詞,那么contain就不能滿足這個需求了。而DFA可以設置最小匹配模式,可以過濾出“大王”是敏感詞。
    性能方面,contain是針對每次比對一個敏感詞,盡管有containAny,但底層還是對每個敏感詞進行比對,也就意味著,有一萬個敏感詞,就要比對一萬次,性能相對很低;而DFA算法不管有多少敏感詞,只需要對目標文本遍歷一次,便可以獲取目標文本涉及到的所有敏感詞。
    2. DFA算法用Java如何構建?
    用java實現實際上就是一層層map的嵌套,核心思想就是通過遍歷文本的每個字符,然后去map中找到對應的key一層層進行比對,具體實現如上。
    3. DFA算法性能如何?
    DFA算法的性能取決于目標文本的長度,遍歷一次目標文本即可獲取所有涉及到的敏感詞,尤其適合針對于實時聊天軟件的敏感詞過濾;假設目標文本的長度為n,它的時間復雜度為O(n)。

    總結

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

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