词典分词

中文分词算法大致分为基于词典规则与基于机器学习两个大学派,词典分词是最简单、最常见的分词算法。
基于词典的分词首先要准备一份充分大的词典,然后依据一定的策略扫描句子,若句子中的某个子串与词典中的某个词匹配,则分词成功。

常见的扫描策略有:正向最大匹配、逆向最大匹配、双向最大匹配和最少词数分词。

切分算法

1.正向最长匹配

考虑越长的单词表达的意义越丰富,于是定义单词越长优先级越高,具体来说就是在以某个下标为起点递增查词的过程中,优先输出更长的单词。这种规则被称为最长匹配算法,下标扫描顺序从前往后就是正向最长匹配,反之就称之为逆向最长匹配。

python伪代码:

def forward_segment(text, dic):
    word_list = []
    i = 0
    while i < len(text):
        longest_word = text[i]
        for j in range(i+1, len(text)-1):
            word = text[i:j]
            if word in dic:
                if len(word)>len(longest_word):
                    longest_word = word
        word_list.append(longest_word)
        i += len(longest_word)
    return word_list

2. 逆最长匹配

逆向最长匹配,只是扫描方向与正向最长匹配相反。
python‘伪代码

def backward_segment(text, dic):
    word_list = []
    i = len(text)-1
    while i >=0:
        longest_word = text[i]
        for j in range(0,i):
            word = text[j:i+1]
            if word in dic:
                if len(word)>len(longest_word):
                    longest_word = word
                    break
        word_list.insert(0,longest_word)
        i -= len(longest_word)
    return word_list

3.双向最长匹配

综合前两种规则:同时执行正向匹配和逆向匹配
1,若两者的词数不同,就返回词数更少的那一个
2.否则,返回两者中单字更少的一个

python伪代码:

def count_single_char(word_list:list):
    return sum(1 for word in word_list if len(word)==1)

def bidirectional_segement(text, dic):
    f = forward_segment(text, dic) #正向最长匹配
    b = backward_segment(text, dic)#逆向最长匹配
    
    if len(f)<len(b):
        return f
    elif len(f)>len(b):
        return b
    else:
        if count_single_char(f)<count_single_char(b):
            return f
        else:
            return b

词典分词的核心价值在于速度而不在于精度。

HanLP的词典分词实现

HanLP的词典分词主要是两种DoubleArrayTriesSegment分词器,这是基于双数组字典树的最长匹配算法
AhoCorasickDoubleArraytrieSegment分词器是基于双数组字典树的AC自动机的算法

from pyhanlp import *

# DoubleArrayTrieSegment分词器
HanLP.Config.ShowTermNature = False #不显示词性
segment1 = DoubleArrayTrieSegment()

print("DoubletrieSegment分词器结果:",
       segment1.seg("为了避免词性影响,我们在程序启动的时候关掉了词性显示"))
segment2 = JClass('com.hankcs.hanlp.seg.Other.AhoCorasickDoubleArraytrieSegment')()

print("AhoCorasickDoubleArrayTrie分词器结果:",
      segment2.seg("为了避免词性影响美观,我们在程序启动的时候关掉了词性显示"))