1. 程式人生 > >java HashMap實現中文分詞器 應用:敏感詞過濾實現

java HashMap實現中文分詞器 應用:敏感詞過濾實現

今天下午部門內部技術分享是分詞器演算法。這次的主講是大名鼎鼎的Ansj分詞器的作者-孫健。

作者簡介:

Ansj分詞器作者
elasticsearch-sql(elasticsearch的sql外掛)作者,支援sql查詢
nlp-lang自然語言工具包發起人
NLPCN(自然語言處理組織)發起人
等等…
網站:http://www.nlpcn.org/
GIT地址:https://github.com/NLPchina

具體作者詳情請百度、Google
大神首先對中文分詞的概念進行詳細的解釋,並對比了傳統分詞和自然語言分詞的區別和優略勢。然後又講到目前中文分詞在應用過程中遇到的一些困難,其中就包括中文歧義的識別(包含交叉歧義、組合歧義、真歧義)、人名識別、地名識別和機構名識別。在這幾種難題中,又以機構名識別最為困難(機構名稱各種簡稱如:北京大學(北大)、騰訊(鵝場)等)。召回率和準確率的關係,正向匹配、逆向匹配等等。生動的講解了分詞的原理和難度所在。
但是講到怎麼實現的時候,大家都是一臉懵逼的,各種演算法(Trie Tree、雙陣列trie樹、CRF模型等)。聽完就什麼都不記得了,呵呵。
不過講到最後的時候給我們分享了下HashMap的一種簡單實現分詞器的思路,意外的收穫。下面通過程式碼說明(五分鐘搞定_)。
HashMap簡單實現的分詞器

public class TokenizerDemo {
private static Map<String, String> map = new HashMap<String, String>();

//詞典中最長詞的長度,map中的key的最長長度
private static final int maxSize = 3;
static{
    //可以從資料庫中載入或詞表中載入
    map.put("中國", "");
    map.put("北京", "");
    map.put("中關村", "");
    map.put("海淀", "");
}

public static void main(String[] args) {
    String text = "中國人民共和國首都是北京,中關村在海淀區。";
    int length = text.length();
    for(int i=0; i<length; i++){
        int endIdx = i+maxSize;
        if(endIdx>length){
            endIdx = length;
        }
        //最大逆序匹配
        for(int j=0; j<maxSize; j++){
            String s = text.substring(i, endIdx);
            if(map.get(s)!=null){
                //跳過匹配過的詞(後面會說明跳過匹配詞的原因)
                i=endIdx-1;
                System.out.println(s);
                break;
            }else{
                endIdx-=1;
                if(endIdx==i){
                    break;
                }
            }
        }
        
    }
}

}

輸出結果:
中國
北京
中關村
海淀

注意:
如果不跳過已經匹配的詞會出現"北京劇院" 拆分成 [北京]、[京劇]、[劇院] 三個詞,
如果跳過匹配過的詞就會拆分成 [北京]、[劇院]。

分詞原理:
從詞典中找出最長詞的長度,這裡為maxSize=3,按照maxSize的長度從文字的第一位(i=0)擷取要抽取的文字【中國人】,然後去Map中查詢是否有對應的值,如果沒有減去一個長度擷取(maxSize-1)【中國】,去Map中查詢,找到則停止當前查詢,接著從匹配當前詞後面的字(i=2)【人民共】開始繼續上述的步驟開始查詢。
程式碼執行的流程如下:
第一次迴圈(i=0):
中國人 -> 無命中(map中沒找到) (j=0)
中國 -> map命中 (j=1) 【註釋:命中後i+2(當前詞)的長度。所以i=2】
第二次迴圈(i=2):
人民共 -> 無命中 (j=0)
人民 -> 無命中 (j=1)
人 -> 無命中 (j=2)
第三次迴圈(i=3):
民共和 -> 無命中 (j=0)
民共 -> 無命中 (j=1)
民 -> 無命中 (j=2)
…依次類推,找出文字中所有匹配詞典中的詞

很簡單的程式碼就說明了分詞器的原理(只是最簡單、能命中詞而以)。
應用場景
敏感詞、文字過濾是一個網站必不可少的功能,可以使用這麼簡單的幾行程式碼實現網站的敏感詞過濾功能,自己這麼簡單幾行程式碼就能實現是不是很棒。
轉載來源:
作者:jijs
連結:https://www.jianshu.com/p/62f4a5596278
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。