自然语言处理调研报告(课程论文、课程设计)题目:最大正向匹配中文分词系统作者:陈炳宏吕荣昌靳蒲王聪祯孙长智所在学院:信息科学与工程学院专业年级:信息安全14-1指导教师:努尔布力职称:副教授2016年10月29日目录一、研究背景、目的及意义 (3)二、研究内容和目标 (4)三、算法实现 (5)四、源代码 (7)1.seg.java 主函数 (7)2. dict.txt 程序调用的字典 (10)3.实验案例 (11)五、小结 (12)一、研究背景、目的及意义中文分词一直都是中文自然语言处理领域的基础研究。
目前,网络上流行的很多中文分词软件都可以在付出较少的代价的同时,具备较高的正确率。
而且不少中文分词软件支持Lucene扩展。
但不过如何实现,目前而言的分词系统绝大多数都是基于中文词典的匹配算法。
在这里我想介绍一下中文分词的一个最基础算法:最大匹配算法(Maximum Matching,以下简称MM算法) 。
MM算法有两种:一种正向最大匹配,一种逆向最大匹配。
二、研究内容和目标1、了解、熟悉中科院中文分词系统。
2、设计程序实现正向最大匹配算法。
3、利用正向最大匹配算法输入例句进行分词,输出分词后的结果。
三、算法实现图一:算法实现正向最大匹配算法:从左到右将待分词文本中的几个连续字符与词表匹配,如果匹配上,则切分出一个词。
但这里有一个问题:要做到最大匹配,并不是第一次匹配到就可以切分的。
算法示例:待分词文本: content[]={"中","华","民","族","从","此","站","起","来","了","。
"}词表: dict[]={"中华", "中华民族" , "从此","站起来"}(1) 从content[1]开始,当扫描到content[2]的时候,发现"中华"已经在词表dict[]中了。
但还不能切分出来,因为我们不知道后面的词语能不能组成更长的词(最大匹配)。
(2) 继续扫描content[3],发现“中华民”并不是dict[]中的词。
但是我们还不能确定是否前面找到的"中华"已经是最大的词了。
因为“中华民”是dict[2]的前缀。
(3) 扫描content[4],发现“中华民族”是dict[]中的词。
继续扫描下去:(4) 当扫描content[5]的时候,发现“中华民族从”并不是词表中的词,也不是词的前缀。
因此可以切分出前面最大的词——"中华民族"。
四、源代码1.seg.java主函数package Segmentation;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.*;import java.util.ArrayList;import java.util.List;import java.util.Scanner;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JTextArea;import com.sun.istack.internal.localization.NullLocalizable;public class Seg extends JFrame{public List<String> dictionary = new ArrayList<String>();public static String request;JFrame frame;JTextArea area1,area2;JButton button1,button2;public void newWindow(){frame=new JFrame();frame.setTitle("正向最大匹配");frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.getContentPane().setLayout(null);frame.setResizable(false);frame.setBounds(300,200,500,400);Seg seg=new Seg();area1=new JTextArea();area1.setEditable(true);area1.setBounds(50,30,400,110);frame.getContentPane().add(area1);area2=new JTextArea();area2.setEditable(false);area2.setBounds(50,240,400,110);frame.getContentPane().add(area2);button1=new JButton("获取帮助");button1.setBounds(100,165,120,50);frame.getContentPane().add(button1);button1.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubarea2.setText("在上方文本框中输入要分词的语句,点击分词即可得到结果\n如有任何问题,请联系软件的开发人员(虽然没有什么卵用)\nVersion_5.6.2\n");}});button2=new JButton(" 分词");button2.setBounds(290,165,100,50);frame.getContentPane().add(button2);button2.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubSeg s=new Seg();s.setDictionary();request=area1.getText()+" ";String response1=s.leftMax();area2.setText(response1);}});}public void setDictionary() {File file=new File(".","dict.txt");BufferedReader reader = null;try {reader = new BufferedReader(new FileReader(file));} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}String temp=null;try {while((temp=reader.readLine())!=null){dictionary.add(temp);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {reader.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{if(reader!=null){try {reader.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}public String leftMax() {String response = "";String s = "";for(int i=0; i<request.length(); i++) {s += request.charAt(i);if(isIn(s, dictionary) && aheadCount(s, dictionary)==1) { response += (s + "/");s = "";} else if(aheadCount(s, dictionary) > 0) {} else {response += (s + "/");s = "";}}return response;}private boolean isIn(String s, List<String> list) {for(int i=0; i<list.size(); i++) {if(s.equals(list.get(i))) return true;}return false;}private int aheadCount(String s, List<String> list) {int count = 0;for(int i=0; i<list.size(); i++) {if((s.length()<=list.get(i).length()) && (s.equals(list.get(i).substring(0, s.length())))) count ++;}return count;}public static void main(String[] args) {Seg seg = new Seg();seg.newWindow();System.out.println("请输入要分词的语句");Scanner scanner=new Scanner(System.in);request=scanner.nextLine()+" ";String response1 = seg.leftMax();System.out.println(response1);}}2. dict.txt 程序调用的字典Ctrl+左击查看字典3.实验案例图二:案例五、小结无论是哪一种分词算法都不是完美的,都有各自的优缺点:基于词典的分词算法的优点是简单,易于实现,缺点是匹配速度慢,不能很好的解决歧义问题,并且也不能很好的解决未登录词的问题;基于统计的分词算法的优点是可以发现所有的歧义切分,缺点是统计语言的精度和决策算法在很大程度上决定了解决歧义的方法,并且速度较慢,需要一个长期的学习过程才能达到一定的程度;由于汉语语言知识的笼统、复杂性,难以将各种语言信息组织成机器可直接读取的形式,因此目前基于理解的分词系统还处在试验阶段。