自己動手寫分詞引擎——逆向最大、正向最大、雙向最大分詞演算法的實現
阿新 • • 發佈:2019-01-31
分詞引擎已經是NLP最成熟的部分了,經歷了:字典分詞,統計分詞等發展之後,除了應付學術中才有的各種變態歧義句之外,目前工業界的分詞引擎對於絕大多數的常見問題已經足以應對,頂多是需要不斷優化新詞字典就可以了。
但不管怎麼樣,對於一個NLPer還是要能夠手寫最簡單的分詞演算法的,這也是面試必備基本功。
一,基於字典的逆向最大分詞演算法
從後向前讀入待分詞字串,讀入字串的長度由分詞字典中最長單詞決定。
之後測試讀入的字串是否存在在字典中,如果存在的話,從原始文字中刪除這個字串,開始重複。
如果讀入的字串不存在在字典中,從左向右減小其長度重複在字典中查詢,如此迴圈。
具體如下例所示:
輸入:我一個人吃飯,
第一次匹配:一個人吃飯
個人吃飯
人吃飯
吃飯 ====》得到一個詞–——吃飯
第二次匹配:我一個人
一個人
個人 ====》得到一個詞—— 個人
第三次匹配:我一
一 ====》得到一個詞– 一
第四次匹配:我 ====》得到一個詞– 我
最後反向最大匹配的結果是:
/我/一/個人/吃飯/
下面上程式碼:
public static void ReverseMaxSegmentation(String input) { if(dictionary.isEmpty()) { initDictionary(); } StringBuffer result = new StringBuffer(); while(input.length()>0) { String temp; //temp就是待分詞的短語 if( input.length()<max_words ) { temp = input; }else { temp = input.substring(input.length() - max_words); } while(temp.length()>0) { if(dictionary.get(temp)!=null || temp.length()==1) { //如果在字典中找到某個詞,這個詞被加入到分詞結果中同時從原始輸入中刪除這個詞 result = new StringBuffer(temp).append("/").append(result); input = input.substring(0, input.length() - temp.length()); break; } else{ //待分詞短語從左向右不斷變短 temp = temp.substring(1); } } } System.out.println(result); }
二,基於字典的正向最大分詞
和逆向正好相反,從輸入Strign的最開始開始讀入待分詞短語,在字典中查詢,如果找不到的話將分詞短語變短,如此迴圈。
變短的時候和逆向分詞相反,從右向左逐步變短。
正向最大匹配方式,最大長度為5
第一次讀入:我一個人吃
我一個人
我一個
我一
我 ====》得到一個詞– 我
第二次讀入:一個人吃飯
一個人吃
一個人
一個 ====》得到一個詞– 一個
第三次讀入:人吃飯
人吃
人 ====》得到一個詞– 人
最後一次讀入:吃飯
====》得到一個詞– 吃飯
最後正向最大匹配的結果是:/我/一個/人/吃飯/
程式碼如下所示:
public static void ForwardMaxSegmentation(String input) { if(dictionary.isEmpty()) { initDictionary(); } StringBuffer result = new StringBuffer(); while(input.length()>0) { String temp; if( input.length()<max_words ) { temp = input; }else { temp = input.substring(0, max_words); } while(temp.length()>0) { if(dictionary.get(temp)!=null || temp.length()==1) { result = result.append(temp).append("/"); input = input.substring(temp.length()); break; } else{ temp = temp.substring(0,temp.length()-1); } } } System.out.println(result); }