Java实现正向最大匹配法和逆向最大匹配法

在自然语言处理中,词是语言中最小的能够独立运用的单位,是信息处理的基本单位。
汉语自动分词是把没有明显分界标志的字串切分为词串。包括:标点符号、数字、数学符号、各种标记、人名、地名、机构名等未登录词的识别。

分词算法

基于规则的自动分词算法

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

基于统计的分词方法

利用字与字间、词与词间的同现频率作为分词的依据, 可以没有建立好的词典需要大规模的训练文本, 用来训练模型参数
优点:不受应用领域的限制;
缺点:训练文本的选择将影响分词结果

正向最大匹配法(Maximum Matching Method,MM)

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

正向最大匹配法的优点:
1. 扫描方向从左到右,从长到短的顺序匹配
2. 原理简单,计算机程序实现容易,复杂度低

MM算法的缺点
忽视“词中有词”的现象,导致切分错误
如切分:”幼儿园地节目”
切分结果为:幼儿园/地/节目/
正确结果为:幼儿/园地/节目/
最大词长难以确定太长,匹配所花时间多,算法时间复杂度提高,太短,不能切分长度超过它的词,导致切分正确率降低

逆向最大匹配法( Reverse Maximum Matching Method,RMM )

逆向最大匹配法就是从右到左的正向最大匹配法。

算法实现:

MM:

public class MM {
    private static StringBuilder result=new StringBuilder();
    private static final int MAXLEN=3; //最大字符数
    private static int len=MAXLEN; //取词长度
    private static int curIndex=0; //当前下标

    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        String sentence=scanner.next();
        maxMatching(sentence);
        System.out.println(result);
    }

    private static void maxMatching(String sentence){
        while(curIndextry {
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        new FileInputStream("./NLP/src/class1/chineseDic.txt"),"GBK"));
                String subStr;
                if (curIndex+len>sentence.length()){
                    subStr=sentence.substring(curIndex,sentence.length());
                }
                else{
                    subStr=sentence.substring(curIndex,curIndex+len);
                }
                String string;
                while ((string=br.readLine())!=null){
                    String[]  line=string.split(",");
                    if (line[0].equals(subStr)){
                        result.append(subStr).append("/");
                        curIndex+=len;
                        len=MAXLEN+1;
                    }
                }
                len--;
                if (len==0){
                    result.append("该字符不存在").append("/");
                    curIndex++;
                    len=MAXLEN;
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

结果(词典为汉语词典,不包含英文字符):

在这一年中,中国的改革开放和现代化建设继续向前迈进。国民经济保持了“高增长、低通胀”的良好发展态势。农业生产再次获得好的收成,企业改革继续深化,人民生活进一步改善。对外经济技术合作与交流不断扩大。

在/ 这/ 一/ 年中/ ,/ 中国/ 的/ 改革/ 开放/ 和/ 现代化/ 建设/ 继续/ 向前/ 迈进/ 。/ 国民/ 经济/ 保持/ 了/ “/ 高/ 增长/ 、/ 低/ 通胀/ ”/ 的/ 良好/ 发展/ 态势/ 。/ 农业/ 生产 / 再次 / 获得/ 好/ 的/ 收成/ ,/ 企业 / 改革 / 继续/ 深化/ ,/ 人民/ 生活/ 进一步/ 改善/ 。/ 对外/ 经济/ 技术/ 合作/ 与/ 交流/ 不断/ 扩大/ 。/


sdf在这fs一年sd中

该字符不存在/ 该字符不存在/ 该字符不存在/ 在/ 这/ 该字符不存在/ 该字符不存在/ 一/ 年/ 该字符不存在/ 该字符不存在/ 中/

RMM:

public class RMM {
    private static LinkedListlist=new LinkedList<>();
    private static final int MAXLEN=3; //最大字符数
    private static int len=MAXLEN; //取词长度
    private static int curIndex; //当前下标

    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        String sentence=scanner.next();
        curIndex=sentence.length();
        maxMatching(sentence);
        for (String s:list) {
            System.out.print(s);
        }
    }

    private static void maxMatching(String sentence){
        while(curIndex>0){
            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        new FileInputStream("./NLP/src/class1/chineseDic.txt"),"GBK"));
                String subStr;
                if (curIndex-len<0){
                    subStr=sentence.substring(0,curIndex);
                }
                else {
                    subStr=sentence.substring(curIndex-len,curIndex);
                }
                String string;
                while ((string=br.readLine())!=null){
                    String[] line=string.split(",");
                    if (line[0].equals(subStr)){
                        list.push(subStr+"/");
                        curIndex-=len;
                        len=MAXLEN+1; //因为后面还有个len--一定会执行,所以必须+1
                    }
                }
                len--;
                if (len==0){
                    list.push("该字符不存在/");
                    curIndex--;
                    len=MAXLEN;
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

结果:

在这一年中,中国的改革开放和现代化建设继续向前迈进。国民经济保持了“高增长、低通胀”的良好发展态势。农业生产再次获得好的收成,企业改革继续深化,人民生活进一步改善。对外经济技术合作与交流不断扩大。

在/ 这/ 一/ 年中/ ,/ 中国/ 的/ 改革/ 开放/ 和/ 现代化/ 建设/ 继续/ 向前/ 迈进/ 。/ 国民/ 经济/ 保持/ 了/ “/ 高/ 增长/ 、/ 低/ 通胀/ ”/ 的/ 良好/ 发展/ 态势/ 。/ 农业/ 生产 / 再次 / 获得/ 好/ 的/ 收成/ ,/ 企业 / 改革 / 继续/ 深化/ ,/ 人民/ 生活/ 进一步/ 改善/ 。/ 对外/ 经济/ 技术/ 合作/ 与/ 交流/ 不断/ 扩大/ 。/


sdf在这fs一年sd中

该字符不存在/ 该字符不存在/ 该字符不存在/ 在/ 这/ 该字符不存在/ 该字符不存在/ 一/ 年/ 该字符不存在/ 该字符不存在/ 中/

你可能感兴趣的:(java,自然语言处理)