日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

需求背景

大家有沒有做過屏蔽敏感詞的需求呢,這個需求一般來說很常見了。比如,系統中有一段話:

我愛吃肯德基

要求【肯德基】三個詞被屏蔽掉,屏蔽后的語句顯示為:

我愛吃***

常規的做法可能是查詢敏感詞庫中的敏感詞,循環每一個敏感詞,然后去輸入的文本中從頭到尾搜索一遍,看是否存在此敏感詞。

但是如果敏感詞很多,對于匹配也是很耗性能的。

這里介紹使用DFA算法匹配敏感詞,并進行處理。性能要優于常規處理方法。

什么是DFA算法

在計算理論中,確定有限狀態自動機確定有限自動機(英語:deterministic finite automaton, DFA)是一個能實現狀態轉移的自動機。對于一個給定的屬于該自動機的狀態和一個屬于該自動機字母表E的字符,它都能根據事先給定的轉移函數轉移到下一個狀態(這個狀態可以是先前那個狀態)。

——來自維基百科

這里的確定意思為:狀態以及引起狀態轉換的事件都是可確定的,不存在"意外"。有限指的是:狀態以及事件的數量都是可窮舉的。

DFA算法在匹配關鍵字上面有廣泛的應用。

如何用Java實現屏蔽敏感詞功能

 

比如上面的關鍵詞【肯德基】,【肯尼瑪】。我們可以抽取成上面的樹狀模型。橢圓表示狀態,狀態與狀態之間的連線叫事件。

當然這里只是簡單地介紹DFA是什么,想深入的童鞋可以看看這篇文章:

常用的DFA最小化算法? - 知乎
-https://www.zhihu.com/question/39767421

里面介紹了如何將正常數據構造成DFA形式。

JAVA代碼實戰

現在我們開始做一個示例吧

現在我們指定了敏感詞【"二愣子","二蛋","狗娃"】,我們按照上面的方式重新構造數據結構:

如何用Java實現屏蔽敏感詞功能

 

如上圖,我們構造了3組數據,每個節點有一個狀態標記,1代表節點結束,也就是敏感詞結束,0代表還未結束。

數據結構Json形式如下:

如何用Java實現屏蔽敏感詞功能

 

接下來就是如何實現代碼了。

首先我們將敏感詞匯添加進入set集合中:

private Set<String> readSensitivewordFile() {
   Set<String> set = Sets.newHashSet();
   set.add("二愣子");
   set.add("二蛋");
   set.add("狗娃");
   return set;
}

當然,實際情況需要從數據庫中讀取,或者從文件中讀取,然后再加載進入set集合。接下來我們將set中的數據重新構造成上面Json格式的,Java這里需要使用Map來存儲。

如何用Java實現屏蔽敏感詞功能

 

我們創建一個sensitiveWordMap來存儲敏感詞,這里實際就是map套map的過程,我們來調試看看map的結構:

如何用Java實現屏蔽敏感詞功能

 

上面的數據結構Map是不是看暈了,其實就是我之前提到Json格式。

如何用Java實現屏蔽敏感詞功能

 

在系統初始化時就將敏感詞構造好。

如何用Java實現屏蔽敏感詞功能

 

我們將敏感詞的結構構造好后,就開始匹配句子了。

如何用Java實現屏蔽敏感詞功能

 

如上代碼,我們需要將句子中的字符一個一個的循環,如果(Map) nowMap.get(word) != null,說明匹配到了敏感詞,這里如果isEnd的結束符為1,代表敏感詞結束,即匹配到了一個敏感詞。

如何用Java實現屏蔽敏感詞功能

 

我們還會遇到上圖的情況,【二蛋】是一個敏感詞,【蛋疼】也是一敏感詞。在【蛋】這個節點中,是【二蛋】的結束節點,是【蛋疼】的開始節點。我們通過代碼:

SensitiveWordFilter.minMatchTYpe == matchType

判斷,如果為true,我們在【蛋】結束之后就不再往下匹配,并將匹配到的index返回。之后再進入下一個循環了。反之。

上面我們拿到匹配到的敏感詞的index,接下來就要將句子中的敏感詞顯示出來了。

如何用Java實現屏蔽敏感詞功能

 

我們將其存入set集合中:

Set<String> sensitiveWordList = new HashSet<>();

這里大家發現一個問題沒有:

獲取敏感詞index循環了一次txt句子,獲取敏感詞字符又循環了一次,大家有沒有辦法減少一次循環呢

這個問題大家闊以思考一下。

然后我們將句子中的敏感詞替換成指定的字符。

如何用Java實現屏蔽敏感詞功能

 

比如我們將敏感詞替換成 "*"。

測試代碼

我們來測試下代碼

如何用Java實現屏蔽敏感詞功能

 

我們選取了《凡人修仙傳》中的一段句子:

"韓立被村里人叫作“二愣子”,可人并不是真愣真傻,反而是村中首屈一指的聰明孩子,但就像其他村中的孩子一樣,除了家里人外,他就很少聽到有人正式叫他名字“韓立”,倒是“二愣子”“二愣子”的稱呼一直伴隨至今。而之所以被人起了個“二愣子”的綽號,也只不過是因為村里已有一個叫“愣子”的孩子了。這也沒啥,村里的其他孩子也是“狗娃”“二蛋”之類的被人一直稱呼著,這些名字也不見得比“二愣子”好聽了哪里去。"

測試的結果為:

如何用Java實現屏蔽敏感詞功能

 

關于DFA的思考

這里我們將敏感詞構造成map,相對于普通的方法,我們不用循環敏感詞,直接用hash表的形式。效率會快很多。但是我們循環了兩次句子txt,如果我們的句子很大,那就對性能有影響,如果我們的敏感詞庫很大,構建的map集合就會很大,這樣就會很占用內存。

進階-一種基于AC自動機的高性能匹配算法

關于DFA算法的問題,這里又有一種AC自動機的算法,也可以實現敏感詞匹配。網上有關于AC自動機的論文,有興趣的童鞋闊以下載看看:

PARA-AC:一種基于AC自動機的高性能匹配算法-AET-電子技術應用
-http://www.chinaaet.com/tech/designApplication/3000125061

什么是AC自動機呢?

AC自動機全稱是Aho-CorasickAutoMaton,和Trie樹一樣是多模式字符串匹配算法。并且它與Trie樹的關系就相當于KMP與BF算法的關系一樣,AC自動機的效率要遠遠超出Trie樹

AC自動機對Trie進行了改進,在Trie的基礎上結合了KMP算法的思想,在樹中加入了類似next數組的失效指針。

AC自動機的構建主要包含以下兩個操作

將多個模式串構建成Trie樹

為Trie樹中每個節點構建失敗指針

如何用Java實現屏蔽敏感詞功能

 

這里給大家推薦一個項目,基于AC自動機的高性能敏感詞匹配:

GitHub - toolgood/ToolGood.Words: 一款高性能敏感詞(非法詞/臟字)檢測過濾組件,附帶繁體簡體互換,支持全角半角互換,漢字轉拼音,模糊搜索等功能。
-https://github.com/toolgood/ToolGood.Words

感謝這個大佬提供的開源項目。

敏感詞構造的數據結構:

如何用Java實現屏蔽敏感詞功能

 

封裝的數據結構為

如何用Java實現屏蔽敏感詞功能

 

匹配替換敏感詞代碼如下:

如何用Java實現屏蔽敏感詞功能

 

代碼中的TrieNode2為存儲的敏感詞結合構

我們用AC自動機算法測試敏感詞

如何用Java實現屏蔽敏感詞功能

 

如上代碼,test為我們要測試的句子,list為設置的敏感詞,測試結果如下:

如何用Java實現屏蔽敏感詞功能

 

我們對比DFA算法的耗時:

如何用Java實現屏蔽敏感詞功能

 

AC自動機耗時低于1ms,而DFA自動機的耗時大于了1ms,當然這里只是初略的測試。需要有意義的性能測試還需要加大敏感詞庫和測試句子的量。

好了,今天的文章到這里就結束了,文章介紹了AC與DFA兩種算法屏蔽敏感詞以及其性能,當然AC自動機的原理還是比較復雜的,本文就不做詳細介紹了,有興趣的同學可以多了解下相關知識。

參考

AC自動機:如何實現敏感詞過濾? -
https://blog.csdn.net/qq_35423154/article/details/109181973

分享到:
標簽:屏蔽 敏感
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定