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

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

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

需求背景

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

我愛吃肯德基

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

我愛吃***

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

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

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

什么是DFA算法

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

——來自維基百科

這里的確定意思為:狀態(tài)以及引起狀態(tài)轉(zhuǎn)換的事件都是可確定的,不存在"意外"。有限指的是:狀態(tài)以及事件的數(shù)量都是可窮舉的。

DFA算法在匹配關(guān)鍵字上面有廣泛的應(yīng)用。

如何用Java實現(xiàn)屏蔽敏感詞功能

 

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

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

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

里面介紹了如何將正常數(shù)據(jù)構(gòu)造成DFA形式。

JAVA代碼實戰(zhàn)

現(xiàn)在我們開始做一個示例吧

現(xiàn)在我們指定了敏感詞【"二愣子","二蛋","狗娃"】,我們按照上面的方式重新構(gòu)造數(shù)據(jù)結(jié)構(gòu):

如何用Java實現(xiàn)屏蔽敏感詞功能

 

如上圖,我們構(gòu)造了3組數(shù)據(jù),每個節(jié)點有一個狀態(tài)標(biāo)記,1代表節(jié)點結(jié)束,也就是敏感詞結(jié)束,0代表還未結(jié)束。

數(shù)據(jù)結(jié)構(gòu)Json形式如下:

如何用Java實現(xiàn)屏蔽敏感詞功能

 

接下來就是如何實現(xiàn)代碼了。

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

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

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

如何用Java實現(xiàn)屏蔽敏感詞功能

 

我們創(chuàng)建一個sensitiveWordMap來存儲敏感詞,這里實際就是map套map的過程,我們來調(diào)試看看map的結(jié)構(gòu):

如何用Java實現(xiàn)屏蔽敏感詞功能

 

上面的數(shù)據(jù)結(jié)構(gòu)Map是不是看暈了,其實就是我之前提到Json格式。

如何用Java實現(xiàn)屏蔽敏感詞功能

 

在系統(tǒng)初始化時就將敏感詞構(gòu)造好。

如何用Java實現(xiàn)屏蔽敏感詞功能

 

我們將敏感詞的結(jié)構(gòu)構(gòu)造好后,就開始匹配句子了。

如何用Java實現(xiàn)屏蔽敏感詞功能

 

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

如何用Java實現(xiàn)屏蔽敏感詞功能

 

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

SensitiveWordFilter.minMatchTYpe == matchType

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

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

如何用Java實現(xiàn)屏蔽敏感詞功能

 

我們將其存入set集合中:

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

這里大家發(fā)現(xiàn)一個問題沒有:

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

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

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

如何用Java實現(xiàn)屏蔽敏感詞功能

 

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

測試代碼

我們來測試下代碼

如何用Java實現(xiàn)屏蔽敏感詞功能

 

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

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

測試的結(jié)果為:

如何用Java實現(xiàn)屏蔽敏感詞功能

 

關(guān)于DFA的思考

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

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

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

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

什么是AC自動機呢?

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

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

AC自動機的構(gòu)建主要包含以下兩個操作

將多個模式串構(gòu)建成Trie樹

為Trie樹中每個節(jié)點構(gòu)建失敗指針

如何用Java實現(xiàn)屏蔽敏感詞功能

 

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

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

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

敏感詞構(gòu)造的數(shù)據(jù)結(jié)構(gòu):

如何用Java實現(xiàn)屏蔽敏感詞功能

 

封裝的數(shù)據(jù)結(jié)構(gòu)為

如何用Java實現(xiàn)屏蔽敏感詞功能

 

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

如何用Java實現(xiàn)屏蔽敏感詞功能

 

代碼中的TrieNode2為存儲的敏感詞結(jié)合構(gòu)

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

如何用Java實現(xiàn)屏蔽敏感詞功能

 

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

如何用Java實現(xiàn)屏蔽敏感詞功能

 

我們對比DFA算法的耗時:

如何用Java實現(xiàn)屏蔽敏感詞功能

 

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

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

參考

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

分享到:
標(biāo)簽:屏蔽 敏感
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

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

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運動步數(shù)有氧達人2018-06-03

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

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定