自己动手写分词引擎——逆向最大、正向最大、双向最大分词算法的实现

分词引擎已经是NLP最成熟的部分了,经历了:字典分词,统计分词等发展之后,除了应付学术中才有的各种变态歧义句之外,目前工业界的分词引擎对于绝大多数的常见问题已经足以应对,顶多是需要不断优化新词字典就可以了。

但不管怎么样,对于一个NLPer还是要能够手写最简单的分词算法的,这也是面试必备基本功。

一,基于字典的逆向最大分词算法

从后向前读入待分词字符串,读入字符串的长度由分词字典中最长单词决定。

之后测试读入的字符串是否存在在字典中,如果存在的话,从原始文本中删除这个字符串,开始重复。

如果读入的字符串不存在在字典中,从左向右减小其长度重复在字典中查找,如此循环。

具体如下例所示:

输入:我一个人吃饭,
第一次匹配:一个人吃饭
个人吃饭
人吃饭
吃饭 ====》得到一个词–——吃饭

第二次匹配:我一个人
一个人
个人 ====》得到一个词—— 个人

第三次匹配:我一
一  ====》得到一个词– 一


第四次匹配:我  ====》得到一个词– 我


最后反向最大匹配的结果是:
/我/一/个人/吃饭/

下面上代码:

public static void ReverseMaxSegmentation(String input) {
        if(dictionary.isEmpty()) {
            initDictionary();
        }
        
        StringBuffer result = new StringBuffer();       
        while(input.length()>0) {
            String temp;
            //temp就是待分词的短语
            if( input.length()<max_words ) {
                temp = input;
            }else {
                temp = input.substring(input.length() - max_words);
            }
            
            while(temp.length()>0) {
                if(dictionary.get(temp)!=null || temp.length()==1) {
                    //如果在字典中找到某个词,这个词被加入到分词结果中同时从原始输入中删除这个词
                    result = new StringBuffer(temp).append("/").append(result);
                    input = input.substring(0, input.length() - temp.length());
                    break;
                }
                else{
                	//待分词短语从左向右不断变短
                    temp = temp.substring(1);
                }
            }
        }
        System.out.println(result);
}

二,基于字典的正向最大分词

和逆向正好相反,从输入Strign的最开始开始读入待分词短语,在字典中查找,如果找不到的话将分词短语变短,如此循环。

变短的时候和逆向分词相反,从右向左逐步变短。

正向最大匹配方式,最大长度为5
第一次读入:我一个人吃
我一个人
我一个
我一
我  ====》得到一个词– 我
第二次读入:一个人吃饭
一个人吃
一个人
一个 ====》得到一个词– 一个
第三次读入:人吃饭
人吃
人 ====》得到一个词– 人
最后一次读入:吃饭
====》得到一个词– 吃饭
最后正向最大匹配的结果是:/我/一个/人/吃饭/

代码如下所示:

    public static void ForwardMaxSegmentation(String input) {
        if(dictionary.isEmpty()) {
            initDictionary();
        }
        
        StringBuffer result = new StringBuffer();
        
        while(input.length()>0) {
            String temp;
            if( input.length()<max_words ) {
                temp = input;
            }else {
                temp = input.substring(0, max_words);
            }
            while(temp.length()>0) {
                if(dictionary.get(temp)!=null || temp.length()==1) {
                    result = result.append(temp).append("/");
                    input = input.substring(temp.length());
                    break;
                }
                else{
                    temp = temp.substring(0,temp.length()-1);
                }
            }
        }
        System.out.println(result);
    }

你可能感兴趣的:(java,算法,面试题,NLP)