基于词表的中文分词算法

基于词表的中文分词算法

正向最大匹配法

对于输入的一段文本从左至右,以贪心的方式切分出当前位置上长度最大的词.正向最大匹配法是基于词典的分词方法,其分词原理是:单词的颗粒度越大,所能表示的含义越确切.

该算法主要分两个步骤:

  1. 一般从一个字符串的开始位置,选择一个最大长度的词长的片段,如果序列不足最大词长,则选择全部序列.
  2. 首先看该片段是否在词典中,如果是,则算为一个分出来的词,如果不是,则从右边开始,减少一个字符,然后看短一点的这个片段是否在词典中,依次循环,直到只剩下一个.
  3. 序列变为第2步骤截取分词后剩下的部分序列.

示例:

0 1 2 3 4 5 6 7 8 9
pos remain characters start characters max matching
0 我毕业于湖北科技学院
1 毕业于湖北科技学院 毕业
3 于湖北科技学院
4 湖北科技学院 湖北科技学院 湖北科技学院

代码实现:

 words_dic = []

def init():
    """
    读取词典文件
    载入词典
    :return:
    """
    with open('dic/dic.txt','r',encoding='utf8') as dic_inp:
        for word in dic_inp:
            words_dic.append(word.strip())

#实现正向匹配算法中的切词方法
def cut_words(raw_sentence,word_dic):
    #统计词典中最长的词
    max_length  = max(len(word) for word in words_dic)
    sentence = raw_sentence.strip()
    #统计序列长度
    words_length = len(sentence)
    #存储切分好的词语
    cut_word_list = []
    while words_length > 0:
        max_cut_length = min(max_length,words_length)
        subSentence = sentence[0 : max_cut_length]
        while max_cut_length > 0:
            if subSentence in words_dic:
                cut_word_list.append(subSentence)
                break
            elif max_cut_length == 1:
                cut_word_list.append(subSentence)
                break
            else:
                max_cut_length = max_cut_length - 1
                subSentence = subSentence[0:max_cut_length]
        sentence = sentence[max_cut_length:]
        words_length = words_length - max_cut_length
    words = "/".join(cut_word_list)
    return words

def main():
    init()
    while True:
        print("请输入您要分词的序列")
        input_str = input()
        if not input_str:
            break
        result = cut_words(input_str,words_dic)
        print("分词结果")
        print(result)

if __name__ == "__main__":
    main()

测试结果:

 请输入您要分词的序列
我毕业于湖北科技学院,就职于华为
分词结果
我/毕业/于/湖北科技学院/,/就职于/华为

逆向最大匹配法

反向最大匹配法的基本原理与正向最大匹配法类似,只是分词顺序变为从左至右

示例

0 1 2 3 4 5 6 7 8 9
pos remain characters start characters max matching
4 我毕业于湖北科技学院 湖北科技学院
3 我毕业于
1 我毕业 毕业
0

代码实现:

words_dic = []

def init():
    with open('dic/dic.txt','r',encoding="utf8") as dic_input:
        for word in dic_input:
            words_dic.append(word.strip())

#实现逆向最大匹配算法的切词算法
def cut_words(raw_sentence,words_dic):
    max_length = max(len(word) for word in words_dic)
    sentence = raw_sentence.strip()
    words_length = len(sentence)
    cut_word_list = []
    while words_length>0:
        max_cut_length = min(max_length,words_length)
        subSentence = sentence[-max_cut_length:]
        while max_cut_length > 0:
            if subSentence in words_dic :
                cut_word_list.append(subSentence)
                break
            elif max_cut_length == 1 :
                cut_word_list.append(subSentence)
                break
            else:
                max_cut_length = max_cut_length - 1
                subSentence = subSentence[-max_cut_length:]
        sentence = sentence[0:-max_cut_length]
        words_length = words_length - max_cut_length
    cut_word_list.reverse()
    words = "/".join(cut_word_list)
    return words

def main():
    init()
    while True:
        print("请输入您要分词的序列")
        input_str = input()
        if not input_str:
            break
        result = cut_words(input_str,words_dic)
        print("分词结果")
        print(result)
if __name__ == '__main__':
    main()

测试结果:

 请输入您要分词的序列
我毕业于湖北科技学院
分词结果
我/毕业/于/湖北科技学院

双向最大匹配算法

双向最大匹配算法是将正向最大匹配算法得到的分词结果和逆向最大匹配法得到的结果进行比较,从而决定正确的分词方法.

启发式规则

  1. 如果正反向分词结果词数不同,则取分词数量较少的那一个.
  2. 如果分词结果次数相同
    a. 分词结果相同,就说明没有歧义,可返回任意一个.
    b. 分词结果不同,返回单字较少的那个

你可能感兴趣的:(基于词表的中文分词算法)