中文分詞是自然語言處理的基石。本文深入剖析逆向最大匹配(Reverse Maximum Matching, RMM)算法原理,並結合開源項目 IK Analyzer 核心源碼(AnalyzeContext、CJKSegmenter)進行逐行解讀。
特點:適合中文「後綴豐富」特性(如「的、了、著」),切分精度通常優於正向最大匹配(MM)。
封裝分詞過程所需的所有狀態:
segmentBuff:字符緩衝區(4096 char)charTypes:字符類型數組(數字、字母、中文、分隔符等)cursor:當前掃描指針(從末尾向前)buffOffset:緩衝區在原文中的偏移量orgLexemes:原始詞元集合(QuickSortSet,按起始位置/長度排序)pathMap:詞元路徑映射(位置 → LexemePath,用於最優路徑選擇)results:最終輸出詞元鏈表buffLocker:緩衝區鎖(多分詞器協同時防止緩衝區被覆蓋)fillBuffer(Reader):分塊讀取,支持大文本流式分詞,處理緩衝區滑動與字符規范化。initCursor():初始化指針到緩衝區末尾,完成字符規范化與類型識別。moveCursor():指針前移 moveIndex+1 位,配合 RMM 回退邏輯。outputToResult():根據 pathMap 輸出最優路徑詞元,單字符兜底輸出。getNextLexeme():輸出迭代器,攔截停用詞,賦值詞元文本。實現 ISegmenter 接口,核心邏輯在 analyze(AnalyzeContext):
public void analyze(AnalyzeContext context) {
// 動態調整最大匹配長度(邊界處理)
if (context.getCursor() < moveIndex) {
moveIndex = context.getCursor();
MATCH_LEN = context.getCursor() + 1;
}
// 詞典查找:從 cursor-moveIndex 開始,長度 MATCH_LEN
Hit hit = Dictionary.getSingleton().matchInMainDict(
context.getSegmentBuff(), context.getCursor() - moveIndex, MATCH_LEN
);
if (hit.isMatch() || MATCH_LEN == 1) {
// 命中或已退避到單字:產出詞元
Lexeme lexeme = new Lexeme(context.getBufferOffset(),
context.getCursor() - moveIndex, MATCH_LEN, Lexeme.TYPE_CJK);
context.addLexeme(lexeme);
context.setMoveIndex(moveIndex);
init(); // 重置移動索引
} else {
// 未命中:回退一位繼續嘗試(遞歸)
if (!hit.isUnmatch() || hit.isUnmatch()) { // 邏輯簡化:未完全不匹配則繼續
--moveIndex;
--MATCH_LEN;
analyze(context); // 遞歸回退
}
}
}
private void init() { moveIndex = 6; MATCH_LEN = 7; } // 默認最大詞長 7
| 設計點 | 實現細節 | 作用 |
|---|---|---|
| 緩衝區滑動 | fillBuffer 中 System.arraycopy 移動未處理數據到頭部 | 支持任意大文本流式處理,內存恆定 |
| 字符規范化 | CharacterUtil.regularize() | 全半角轉換、大小寫統一、特殊字符處理 |
| 字符類型識別 | CharacterUtil.identifyCharType() | 區分中文、英文、數字、分隔符,支持子分詞器分工 |
| 緩衝區鎖 | buffLocker Set | 多分詞器(如 CJK、英文、數字)串行處理同一緩衝區時防衝突 |
| 最優路徑選擇 | pathMap + QuickSortSet | 詞元按起始位置排序,動態規劃選擇詞數最少/詞長最大路徑 |
| 數量詞合併 | compound() 中 TYPE_NUM + TYPE_QUANTIFIER → TYPE_NUM_QUAN | 「三個」合併為一詞,提升語義完整性 |
| 停用詞過濾 | Dictionary.isStopWord() 在 getNextLexeme 中攔截 | 輸出階段過濾「的、是、在」等無語義詞 |
IK Analyzer 的 RMM 實現展示了工業級分詞器的核心架構:流式緩衝管理、多類型字符協同分詞、詞典驅動的逆向匹配、最優路徑動態規劃、詞元後處理(合併/過濾)。理解這些模塊,是掌握中文 NLP 基礎設施的關鍵一步。