中文文本分词之——反向最大匹配法

什么是中文分词

中文分词(Chinese Word Segmentation) 指的是将一个汉字序列切分成一个个单独的词。分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。我们知道,在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符,虽然英文也同样存在短语的划分问题,不过在词这一层上,中文比之英文要复杂得多、困难得多。(摘自百度百科)
简单地说,我们问题的输入是一系列中文句子、段落或者文章,输出是将这些材料中所有的词语进行分割后的文本。
例:输入:深化国资国企改革,国有企业优化重组、提质增效取得新进展。
输出:深化\国资\国企\改革\,\国有\企业\优化\重组\、\提质\增效\取得\新进展\。\

反向最大匹配方法

算法思想

反向最大匹配算法的思想较为简单。就是根据事先最备好的词典,从后往前进行匹配,假如有匹配到的词直接分割,若没有的话减少最左边一个词然后继续匹配,直至所有的句子匹配完毕。

算法步骤

  1. 在句子未匹配部分的末尾截取词典中最长词长度的文本;
  2. 将截取的文本在词典中进行匹配;
  3. 若匹配成功,返回第一步,直到全部句子匹配结束;
  4. 若为匹配成功,将文本去掉最左边的一个词,返回第二步。

算法代码

package divison;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

public class Divison {
	private static Set dic = new HashSet();
	private static int maxlength = 0; 
	
	private static void getDictionary(String fileName) {
		String[] dicStrings = null;
		FileReader in = null;
		try {
			in = new FileReader(fileName);
		} catch (FileNotFoundException e) {
			// TODO 自动生成的 catch 块
			System.out.println("文件读入失败!");
			e.printStackTrace();
		}
		BufferedReader reader = new BufferedReader(in);
		try {
			for(String temps = reader.readLine();temps!=null;temps = reader.readLine()) {
				dicStrings = temps.split(" |1|2|3|4|5|6|7|8|9|0|\n");
				for (int i = 0; i < dicStrings.length; i++) {
					dic.add(dicStrings[i]);
					if(dicStrings[i].length() > maxlength) {
						maxlength = dicStrings[i].length();
					}
				}
			}
			in.close();
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}
	private static void makeDivison(String filename) {
		FileReader in = null;
		String result = null;
		try {
			in = new FileReader(filename);
			BufferedWriter buf = new BufferedWriter(new FileWriter("src\\doc\\分词结果.txt"));
			BufferedReader reader = new BufferedReader(in);
			for(String temps = reader.readLine();temps!=null;temps = reader.readLine()) {
				System.out.println(temps);
				System.out.println("");
				result = aMatch(dic, temps);
				System.out.println(result);
				System.out.println("");
				buf.write(result);
				buf.newLine();
			}
			in.close();
			buf.close();	
		} catch (FileNotFoundException e) {
			// TODO 自动生成的 catch 块
			System.out.println("文件读入失败!");
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO 自动生成的 catch 块
			e1.printStackTrace();
		}
	}
	private static String aMatch(Set dic,String waitmatch) {
		int first = waitmatch.length() - maxlength;
		if (first < 0) {
			first = 0;
		}
		int last = waitmatch.length();
		String subtemp = null;
		String result = "";
		boolean success = false;
		while (last != 0) {
			while(first < last - 1){
				subtemp = waitmatch.substring(first, last);
				if (dic.contains(subtemp)) {
					success = true;
					result =subtemp + "\\" + result;
					break;
				}
				first++;
			}
			if (!success) {
				subtemp = waitmatch.substring(first, last);
				result =subtemp + "\\" + result;
			}
			last = first;
			success = false;
			if(last - maxlength >= 0) {
				first = last - maxlength;
			}
			else {
				first = 0;
			}
		}
		return result;
	}
	public static void main(String[] args) {
		String filename = "src\\doc\\未处理字典.txt";
		String filewait = "src\\doc\\待分词文本.txt";
		getDictionary(filename);
		System.out.println("词典提取成功!"+"\n所提取词最长为:"+maxlength+"\n词数总量为:"+dic.size());
		makeDivison(filewait);
		System.out.println("分词成功!");
	}
}

运行结果

原文本:
中文文本分词之——反向最大匹配法_第1张图片
分词结果:中文文本分词之——反向最大匹配法_第2张图片

说明

  1. 该代码并没有处理连续的数字(123…或一二三…);
  2. 该代码对于歧义也并没有多余的处理;
  3. 该代码使用的词典词数为十万级;
  4. 项目文件见1170300629/-/tree/master/ChineseSegmentation.
    (建议首先阅读README.md)。

你可能感兴趣的:(中文分词)