一个后项最大匹配分词

 最近写了一个后项最大匹配的分词,其中构件词表的过程是参考了网上的一个已经有了的分词程序;

代码如下:(其中有两个词表文件interpunction.txt和simplexu8.txt,其中前者是用来定义过滤其中的一些特殊符号,后者是词表文件)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Locale;
import java.util.TreeMap;
import java.util.TreeSet;
import java.io.File;
import java.io.FileInputStream;

public class mySplitter
{
 private boolean flag; //判断是否处理类似空格,标点等符号
 private TreeSet interpunction; //标点符号的集合,用来过滤输入字符串的标点符号
    private static TreeSet CJK = new TreeSet(); //存放中文词的集合
 private static int maxlength = 0; //词典中最长的词的长度

 static //构造中文词集合
 {
  String newword = null;
  try
  {
   File file = new File("simplexu8.txt"); 
   FileInputStream in0 = new FileInputStream(file);
   BufferedReader in = new BufferedReader(new InputStreamReader(in0,"UTF-8"));
   in.readLine();
   maxlength = Integer.parseInt(in.readLine().toString()); //获取最大长度
   //System.out.println(maxlength);
   while ((newword = in.readLine()) != null)
   {
    CJK.add(newword.intern());
    //System.out.println(newword.intern());
   }
   in.close();
  }
  catch (IOException e)
  {
   e.printStackTrace();
  }
 }

 public mySplitter() //默认实现标点符号过滤
 {
  this.flag = true;
  this.interpunction = new TreeSet();
  this.init();
 }

 public mySplitter(boolean flag) //flag为true时实现标点符号过滤,否则不过滤标点符号
 {
  this.flag = flag;
  this.interpunction = new TreeSet();
  if(flag)
   this.init();
 }
 
 public String split(String s , String seprator) //对指定的字符串s进行切分,切分出来的词用指定的字符串seprator进行分隔
 {
  if(s.length() <= 0)
   return null;
  StringBuffer result = new StringBuffer(); //存放最终返回结果
  StringBuffer cur_word = new StringBuffer(); //存放当前正在处理的字符串
  int cur_pos = s.length() - 1; //存放当前处理位置(在s中)
  char cur_char = s.charAt(cur_pos);
  while(isInterpunction(cur_char) && cur_pos > 0) //防止最后一个词是标点符号(如果是不处理标点符号,则isInterpunction函数可以保证结果的正确性)
  {
   cur_pos--;
   cur_char = s.charAt(cur_pos);
  }
  if(isInterpunction(cur_char) && cur_pos == 0)
   return null;
  cur_word.insert(0, cur_char);
  if(isCJK(cur_char)) //如果输入中文字符进行特殊对待,因为下面的中文处理算法在处理中文的时候不占用这个缓冲区cur_word
  {
   cur_pos++;
   cur_word.setLength(0);
  }
  while(cur_pos > 0) //进行核心处理
  {
   cur_pos--;
   cur_char = s.charAt(cur_pos);
   if(isCJK(cur_char)) //匹配中文词
   {
    if(cur_word.length() > 0) //如果缓冲区中有词,先输出到结果中,因为处理中文时候不占用缓冲区cur_word
    {
     result.append(cur_word.toString() + seprator);
     cur_word.setLength(0);
    }
    if(cur_word.length() <= 0)
    {
          
     int len = (maxlength - 1) > cur_pos ? cur_pos : (maxlength - 1); //防止处理到文章的最前面了
     int i = 0;
     while(i < len) //进行后项最大匹配
     {
      String a = s.substring(cur_pos - len + i , cur_pos + 1); //不断缩小匹配的长度,直到匹配成功
      if(CJK.contains(a)) //判断是否成词
      {
       result.append(a + seprator);
       cur_pos = cur_pos - len + i;
       //System.out.println("if内 : "+a);
       break;
      }
      i++;
     }
     if(i == len) //如果没有匹配的词
     {
      result.append(s.substring(cur_pos , cur_pos + 1) + seprator);
      //System.out.println("i=len : "+s.substring(cur_pos , cur_pos + 1));
     }
    }
    continue;
   }
   else if(isInterpunction(cur_char)) //过滤标点符号(如果是不处理标点符号,则isInterpunction函数可以保证结果的正确性)
   {
    if(cur_word.length() > 0)
    {
     result.append(cur_word.toString() + seprator);
     cur_word.setLength(0);
    }
    continue;
   }
   else //处理数字,英文单词
   {
    cur_word.insert(0, cur_char);
    continue;
   }
  }
  if(cur_word.length() > 0)
  {
   result.append(cur_word.toString() + seprator);
   cur_word.setLength(0);
  }
  return result.toString();
 }

 private void init() //初始化interpunction集合
 {
  String dataline;
  try
  {
   InputStream data = getClass().getResourceAsStream("interpunction.txt");
   BufferedReader in = new BufferedReader(new InputStreamReader(data, "UTF-8"));
   in.readLine();
   while ((dataline = in.readLine()) != null)
   {
    if (dataline.length() == 0)
    {
     continue;
    }
    this.interpunction.add(dataline.intern());
    //System.out.println(dataline.intern());
   }
   in.close();
  }
  catch (Exception e)
  {
   e.printStackTrace();
  }
 }

 public boolean getFlag()
 {
  return this.flag;
 }

 public void setFlag(boolean flag)
 {
  this.flag = flag;
 }

 private boolean isCJK(char c)
 {
  if(Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS)
  {
   return true;
  }
  return false;
 }

 private boolean isInterpunction(char c)
 {
  if(this.flag)
  {
   return this.interpunction.contains(new Character(c).toString().intern());
  }
  return false;
 }

 public static void main(String args[])
 {
  mySplitter t = new mySplitter();
  System.out.println(t.split("                 jasd 我的天堂" , "#"));
 }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值