中文分词引擎 java 实现 — 正向最大、逆向最大、双向最大匹配法

本文详细介绍了如何使用Java实现中文分词的正向最大匹配法、逆向最大匹配法和双向最大匹配法。通过具体的分词实例,展示了算法的工作流程,并提供了相应的代码实现。同时,提到了字典载入和自定义词的处理,以及歧义句的测试,强调了分词效果与字典质量的关联性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

正向最大匹配法

分词目标:

在词典中进行扫描,尽可能地选择与词典中最长单词匹配的词作为目标分词,然后进行下一次匹配。

算法流程

假设词典中最长的单词为 5 个(MAX_LENGTH),那么最大匹配的起始子串字数也为 5 个

(1)扫描字典,测试读入的子串是否在字典中

(2)如果存在,则从输入中删除掉该子串,重新按照规则取子串,重复(1)

(3)如果不存在于字典中,则从右向左减少子串长度,重复(1)

分词实例:

比如说输入 “北京大学生前来应聘”,

  1. 第一轮:取子串 “北京大学生”,正向取词,如果匹配失败,每次去掉匹配字段最后面的一个字
    • “北京大学生”,扫描 5 字词典,没有匹配,子串长度减 1 变为“北京大学”
    • “北京大学”,扫描 4 字词典,有匹配,输出“北京大学”,输入变为“生前来应聘”
  2. 第二轮:取子串“生前来应聘”
    • “生前来应聘”,扫描 5 字词典,没有匹配,子串长度减 1 变为“生前来应”
    • “生前来应”,扫描 4 字词典,没有匹配,子串长度减 1 变为“生前来”
    • “生前来”,扫描 3 字词典,没有匹配,子串长度减 1 变为“生前”
    • “生前”,扫描 2 字词典,有匹配,输出“生前”,输入变为“来应聘””
  3. 第三轮:取子串“来应聘”
    • “来应聘”,扫描 3 字词典,没有匹配,子串长度减 1 变为“来应”
    • “来应”,扫描 2 字词典,没有匹配,子串长度减 1 变为“来”
    • 颗粒度最小为 1,直接输出“来”,输入变为“应聘”
  4. 第四轮:取子串“应聘”
    • “应聘”,扫描 2 字词典,有匹配,输出“应聘”,输入变为“”
  5. 输入长度为0,扫描终止


正向匹配法最终的切分结果为:”北京大学 / 生前 / 来 / 应聘”

正向匹配法实现代码如下:

public List<String> leftMax(String str) {

        List<String> results = new ArrayList<String>();
        String input = str;

        while( input.length() > 0 ) {

            String subSeq;
            // 每次取小于或者等于最大字典长度的子串进行匹配
            if( input.length() < MAX_LENGTH) 
                subSeq = input;
            else
                subSeq = input.substring(0, MAX_LENGTH);

            while( subSeq.length() > 0 ) {
                // 如果字典中含有该子串或者子串颗粒度为1,子串匹配成功
                if( dictionary.contains(subSeq) || subSeq.length() == 1) {
                    results.add(subSeq);
                    // 输入中从前向后去掉已经匹配的子串
                    input = input.substring(subSeq.length());
                    break;      // 退出循环,进行下一次匹配
                } else {
                    // 去掉匹配字段最后面的一个字
                    subSeq = subSeq.substring(0, subSeq.length() - 1);
                }   
            }

        }
        return results;
    }


逆向最大匹配法

分词目标:

在词典中进行扫描,尽可能地选择与词典中最长单词匹配的词作为目标分词,然后进行下一次匹配。

在实践中,逆向最大匹配算法性能优于正向最大匹配算法。

算法流程

假设词典中最长的单词为 5 个(MAX_LENGTH),那么最大匹配的起始子串字数也为 5 个

(1)扫描字典,测试读入的子串是否在字典中

(2)如果存在,则从输入中删除掉该子串,重新按照规则取子串,重复(1)

(3)如果不存在于字典中,则从左向右减少子串长度,重复(1)

分词实例:

比如说输入 “北京大学生前来应聘”,

  1. 第一轮:取子串 “生前来应聘”,逆向取词,如果匹配失败,每次去掉匹配字段最前面的一个字
    • “生前来应聘”,扫描 5 字词典,没有匹配,字串长度减 1 变为“前来应聘”
    • “前来应聘”,扫描 4 字词典,没有匹配,字串长度减 1 变为“来应聘”
    • “来应聘”,扫描 3 字词典,没有匹配,字串长度减 1 变为“应聘”
    • “应聘”,扫描 2 字词典,有匹配,输出“应聘”,输入变为“大学生前来”
  2. 第二轮:取子串“大学生前来”
    • “大学生前来”,扫描 5 字词典,没有匹配,字串长度减 1 变为“学生前来”
    • “学生前来”,扫描 4 字词典,没有匹配,字串长度减 1 变为“生前来”
    • “生前来”,扫描 3 字词典,没有匹配,字串长度减 1 变为“前来”
    • “前来”,扫描 2 字词典,有匹配,输出“前来”,输入变为“北京大学生”
  3. 第三轮:取子串“北京大学生”
    • “北京大学生”,扫描 5 字词典,没有匹配,字串长度减 1 变为“京大学生”
    • “京大学生”,扫描 4 字词典,没有匹配,字串长度减 1 变为“大学生”
    • “大学生”,扫描 3 字词典,有匹配,输出“大学生”,输入变为
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值