java中文分词的简单实现

中文分词

通俗来讲,中文分词是指将一句中文句子中的所有中文词汇相互分隔开来。它是文本挖掘的基础,有着十分广阔的应用前景。下面,我们来看一看对于这个技术的简单实现。

算法

对于中文分词技术的实现,有许多算法可以完成,目前大致可以把算法分为三大类:

  1. 基于字符串匹配的分词方法;
  2. 基于理解的分词方法;
  3. 基于统计的分词方法。

其中,基于字符串匹配的分词方法是把中文句子按照一定的策略将待分析的汉字串与已知且足够大的中文词典库进行比对,从而达到分词效果。而我们通常使用最多的分词策略,大致有三类,正向最大匹配法,逆向最大匹配法和最少切分法。

基于理解的分词方法是指让计算机模拟人对句子的理解进行分词。基于统计的分词方法是指找出上下文中出现较多的汉字组合,将这些组合视为词汇,代入到原文中进行分词。

在这里,我们就使用字符串匹配的分词方法,利用逆向最大匹配的策略,对中文句子进行简单的分词。

算法思路

逆向最大匹配法大致思想为:将整个字符串作为一个“词组”带入到词典中进行比对,若不成功,删除第一个字符,继续进行如此操作,直到成功或者只剩下最后一个字,再把结果放入一个字符串的数组中,最后删除原句中的结果,继续上面的操作。下面我将用一个例子解释这个操作:

原句:今晚月亮真漂亮啊
词典:“今晚”,“月亮”,“漂亮”
第一次代入:今晚月亮真漂亮啊(在词典中没有该词汇,删除首字符继续比对)
删除首字符:晚月亮真漂亮啊(在词典中没有该词汇,删除首字符继续比对)
删除首字符:月亮真漂亮啊(在词典中没有该词汇,删除首字符继续比对)
删除首字符:亮真漂亮啊(在词典中没有该词汇,删除首字符继续比对)

删除首字符:啊(在词典中没有该词汇,只剩下一个字,放入结果数组,并删除位于句尾的最后这个字,进行第二次代入)
第二次代入:今晚月亮真漂亮(在词典中没有该词汇,删除首字符继续比对)

删除首字符:漂亮(在词典中找到词汇“漂亮”,放入结果数组,并删除位于句尾的结果“漂亮”,进行第三次代入)

算法实现

下面是实现该算法的流程图(摘自网络,图片地址:https://p2.ssl.qhimgs1.com/bdr/240/t01d394ac7e308b34be.jpg)

在这里插入图片描述

代码及注释

public class secondwork {
	public static void main(String args[])
	{
		String[] cs =  {"你好","请问","什么","名字"};//词典
		String a = "你好!请问你叫什么名字?";
		System.out.print("原句:");
		System.out.print(a + '\n');
		System.out.print("拆分后为:");
		String[] cs2 = new String[100]; //结果数组
		int jud=0;//找到匹配字符串与否的标志
		int j=0;
		String temp=null;//初始化临时字符串
		for(;a.length()>0;)
		{
			for(int i = 0;i<a.length();i++)
			{
				temp = a.substring(i);//每次截取掉首个字符
				if(isin(cs,temp) == true)//如果目标字符串在数组中
				{
					cs2[j] = temp;
					jud = 1;
					int number = temp.length();
					a = a.substring(0,a.length()-number);
				}
			}
			if(jud == 0)//没有找到匹配字符串
			{
				cs2[j] = a.substring(a.length()-1,a.length());//将最后一个元素放在cs2里面
				a = a.substring(0, a.length()-1);//截掉最后一个元素继续循环。	
			}
			jud = 0;
			j++;
		}
		for(;j >= 0;j--)
		{
			if(cs2[j] != null)
				System.out.print(cs2[j]+"   ");
		}
	}
	
	/*
	
	 * 下面为判断字符串是否在词典中的函数方法
	
	*/
	
	static public boolean isin(String[] cs,String temp)//判断目标字符串是否在对比字符串数组中
	{
		int i;
		for(i = 0;i<cs.length;)
		{
			if(temp.equals(cs[i]))
				i = cs.length+1;
			else
				i++;
		}
		if(i == cs.length+1)
			return true;
		else
			return false;
	}
}

输出结果如下:
在这里插入图片描述

评价

逆向最大匹配法的思想使得这个策略十分容易实现,具有非常明显的简单易懂的特点,实现代码也不算太长。但是,逆向最大匹配算法对于一些比较特殊的句子,分词准确率可能会降低。例如下面这个句子:

爱迪生发明了很多东西

如果你的词典足够大,你会发现,按照逆向最大匹配的方法,计算机会将“明了”看做一个中文词汇分隔出来,继续向下走,计算机将分出词汇“生发”,这样一来,就会造成 “爱迪 生发 明了” 的错误。

没关系!我们还有正向最大匹配法,我们可以用正向最大匹配法,对这个句子进行分词,结果就对了。但是正向最大匹配法也会出现bug,怎么办呢,我们可以将正向和逆向结合,这样就是另外一种分词策略:双向最大匹配法,大大降低了出现bug的概率。

结语

任何算法都有它的优劣性,我们在使用算法时,不仅要使用算法,更要去考虑怎么样去优化算法,使算法更加贴合自己的需求。

以上便是我对中文分词的简单实现,感谢阅读!

import WordSegment.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.*; import java.io.File; import java.util.Vector; import javax.swing.*; /** * */ /** * @author Truman * */ public class WordSegDemoFrame extends JFrame implements ActionListener { final static int ALGO_FMM = 1; final static int ALGO_BMM = 2; private JMenuBar menuBar = new JMenuBar(); private JMenuItem openDicItem, closeItem; private JRadioButtonMenuItem fmmItem, bmmItem; private JMenuItem openTrainFileItem, saveDicItem, aboutItem; private JButton btSeg; private JTextField tfInput; private JTextArea taOutput; private JPanel panel; JLabel infoDic, infoAlgo; private WordSegment seger; private DicTrainer trainer = new DicTrainer(); private void initFrame() { setTitle("Mini分词器"); setDefaultCloseOperation(EXIT_ON_CLOSE); setJMenuBar(menuBar); JMenu fileMenu = new JMenu("文件"); JMenu algorithmMenu = new JMenu("分词算法"); JMenu trainMenu = new JMenu("训练语料"); JMenu helpMenu = new JMenu("帮助"); openDicItem = fileMenu.add("载入词典"); fileMenu.addSeparator(); closeItem = fileMenu.add("退出"); algorithmMenu.add(fmmItem = new JRadioButtonMenuItem("正向最大匹配", true)); algorithmMenu.add(bmmItem = new JRadioButtonMenuItem("逆向最大匹配", false)); ButtonGroup algorithms = new ButtonGroup(); algorithms.add(fmmItem); algorithms.add(bmmItem); openTrainFileItem = trainMenu.add("载入并训练语料"); saveDicItem = trainMenu.add("保存词典"); aboutItem = helpMenu.add("关于Word Segment Demo"); menuBar.add(fileMenu); menuBar.add(algorithmMenu); menuBar.add(trainMenu); menuBar.add(helpMenu); openDicItem.addActionListener(this); closeItem.addActionListener(this); openTrainFileItem.addActionListener(this); saveDicItem.addActionListener(this); aboutItem.addActionListener(this); fmmItem.addActionListener(this); bmmItem.addActionListener(this); JPanel topPanel = new JPanel(); topPanel.setLayout(new FlowLayout());
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值