基于规则的双向最大匹配中文分词 Java

1 概述

汉语自动分词是把没有明显分界标志的字串切分为词串。包括:标点符号、数字、数学符号、各种 标记、人名、地名、机构名等未登录词的识别。本篇博客使用Java编程语言实现基于规则的双向最大匹配算法,算是NLP里的一个“Hello world”了。

2 理论描述

基于规则的自动分词算法
(1) 事先人工建立好分词词典和分词规则库。
(2) 原理为基于字符串匹配进行分词,这样就要 求有足够大的词表为依据。
(3) 通过一定的算法来实现,如正向最大匹配法、 逆向最大匹配法、双向匹配法等。
(4) 缺点:当分词词典所收容的词较少时,显然覆盖度就有限,分词的正确率就低。

3 算法描述

本文实现双向最大匹配算法,具体算法描述如下:
设MaxLen表示最大词长,D为分词词典。
MM:正向最大匹配法 (Maximum Matching Method,MM)
(1) 从待切分语料中按正向取长度为MaxLen的字串subStr,令 wordLen=MaxLen;
(2) 把subStr与D中的词相匹配;
(3) 若匹配成功,则认为该字串为词,指向待切分语料的指针向前移wordLen个汉字(字节),返回到(1);
(4) 若不成功:如果wordLen>1,则将Len减1,从待切分语料中取长度为wordLen的字串subStr,返回到(2)。否则,得到长度为1的单字词,指向待切分语料的指针向前移1个汉字, 返回(1)。

/**
 * 正向最大匹配算法
 *
 * @param source     需要进行分词的字符串
 * @param wordLen    搜索的词的长度
 * @param currentPos 分词进行的当前位置
 */
private void MM(String source, int wordLen, int currentPos) {
    int sLength = source.length();  // 获取当前字符串长度
    if (currentPos + 1 > sLength)
        return; // 递归结束
    while ((currentPos + wordLen) > sLength) {
        wordLen = wordLen - 1;  // 边界处理
    }
    
	// 获取子串
    String subStr = source.substring(currentPos, currentPos + wordLen); 
    if (dict.contains(subStr)) {
        result = result + subStr + "/ ";

        currentPos = currentPos + wordLen;  // 找到,搜索位置后移动
        MM(source, MAX_LEN, currentPos);
    } else {
        if (wordLen >= 1) {
            wordLen = wordLen - 1;  // 当前长度找不到,搜索词的字数减小
            MM(source, wordLen, currentPos);
        }
    }
}

RMM:逆向最大匹配法 (Reverse Maximum Matching Method,RMM)
(1) 从待切分语料中按逆向取长度为MaxLen的字串subStr,令 wordLen=MaxLen;
(2) 把subStr与D中的词相匹配;
(3) 若匹配成功,则认为该字串为词,指向待切分语料的指针向后移wordLen个汉字(字节),返回到(1);
(4) 若不成功:如果wordLen>1,则将Len减1,从待切分语料中取长度为wordLen的字串subStr,返回到(2)。否则,得到长度为1的单字词,指向待切分语料的指针向前移1个汉字, 返回(1)。

/**
  * 逆向最大匹配算法
  *
  * @param source     需要进行分词的字符串
  * @param wordLen    搜索词长度
  * @param currentPos 分词进行的当前位置
  */
 private void RMM(String source, int wordLen, int currentPos) {

     if (currentPos < 1)
         return;
     if (currentPos < wordLen) {
         wordLen = currentPos;  // 边界处理
     }
	 // 获取子串
     String subStr = source.substring(currentPos - wordLen, currentPos); 

     if (dict.contains(subStr)) {
         result = subStr + "/ " + result;

         currentPos = currentPos - wordLen;  // 找到,搜索位置前移动
         RMM(source, MAX_LEN, currentPos);
     } else {
         if (wordLen >= 1) {
             wordLen = wordLen - 1;
             RMM(source, wordLen, currentPos);
         }
     }
 }

4 详例描述

对外经济技术合作与交流不断扩大。为例,详细描述算法如下:
MM:(以MaxLen=4为例)

对外经济——>不匹配,wordLen-1
对外经——>不匹配,wordLen-1
对外——>找到匹配,指针移动,wordLen=4
技术合作——>不匹配,wordLen-1

结果:对外/ 经济/ 技术/ 合作/ 与/ 交流/ 不断/ 扩大/ 。/

RMM:(以MaxLen=4为例)

断扩大。——>不匹配,wordLen-1
扩大。——>不匹配,wordLen-1
大。——>不匹配,wordLen-1
。——>找到匹配,指针移动,wordLen=4

结果:对外/ 经济/ 技术/ 合作/ 与/ 交流/ 不断/ 扩大/ 。/

5 其他情况

有文章表明90%情况下正向匹配和逆向匹配的结果是相同的,当正向和逆向匹配结果不吻合时,我们可以进行人工消歧,或者使用其他启发式规则进行判断,这里不再赘述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值