`
billgmh
  • 浏览: 65503 次
  • 性别: Icon_minigender_1
  • 来自: 广东广州
社区版块
存档分类
最新评论

原创中文分词代码分享(1.2)——词典接口

阅读更多
最后说一下双Hash结构的实现类DoubleHashDictionary类:
java 代码
 
  1. /* 
  2.  * @作者:Hades , 创建日期:2006-11-17 
  3.  * 
  4.  * 汕头大学03计算机本科 
  5.  *  
  6.  */  
  7. package edu.stu.cn.segment.matching.dictionary;  
  8.   
  9. import java.io.BufferedReader;  
  10. import java.io.FileReader;  
  11. import java.io.IOException;  
  12. import java.io.PrintStream;  
  13. import java.io.Serializable;  
  14. import java.util.ArrayList;  
  15. import java.util.Collections;  
  16. import java.util.Hashtable;  
  17. import java.util.LinkedList;  
  18.   
  19. /** 
  20.  * @author Hades Guan 基于词典分词方法中使用的词典实例 
  21.  */  
  22. public class DoubleHashDictionary implements Serializable, DictionaryImpl  
  23. {  
  24.     /** 
  25.      * serialVersionUID 的注释 
  26.      */  
  27.     private static final long serialVersionUID = -6085097706592874294L;  
  28.   
  29.     /** 
  30.      * 词典索引表 
  31.      */  
  32.     private Hashtablenull;  
  33.   
  34.     /** 
  35.      * 最大词长 
  36.      */  
  37.     private int maxWordLen = 0;  
  38.   
  39.     /** 
  40.      * 词典长度 
  41.      */  
  42.     private int wordCount = 0;  
  43.   
  44.     /** 
  45.      * 删除词典中的词word 
  46.      *  
  47.      * @param word 
  48.      *            待删除的词汇 
  49.      */  
  50.     public void deleteWord(String word)  
  51.     {  
  52.         if (word == null)  
  53.             return;  
  54.   
  55.         // 过滤多于空格  
  56.         word = word.trim();  
  57.         // 获取词长  
  58.         int len = word.length();  
  59.         // 判断词长为len的二级索引表(首字hash表)是否为空  
  60.         if (this.indexTable[len - 1] == null)  
  61.             return;  
  62.         // 获取词的首字  
  63.         String fch = word.substring(01);  
  64.         // 首字对应的词汇列表  
  65.         ArrayList<string> wal = null;  </string>
  66.         if (this.indexTable[len - 1].containsKey(fch))  
  67.             wal = this.indexTable[len - 1].get(fch);  
  68.         else  
  69.             return;  
  70.   
  71.         // 判断是否包含该词汇  
  72.         String str = word.substring(1, len);  
  73.         if (Collections.binarySearch(wal, str) >= 0)  
  74.         {  
  75.             wal.remove(str);  
  76.             this.indexTable[len - 1].put(fch, wal);  
  77.         }  
  78.         else  
  79.             return;  
  80.     }  
  81.   
  82.     /** 
  83.      * @return 返回 maxWordLen。 
  84.      */  
  85.     public int getMaxWordLen()  
  86.     {  
  87.         return maxWordLen;  
  88.     }  
  89.   
  90.     /** 
  91.      * @return 返回 wordCount。 
  92.      */  
  93.     public int getWordCount()  
  94.     {  
  95.         return wordCount;  
  96.     }  
  97.   
  98.     /** 
  99.      * 将词汇word插入到词典文件中 
  100.      *  
  101.      * @param word 
  102.      *            待插入的词汇 
  103.      */  
  104.     public void insertWord(String word)  
  105.     {  
  106.         if (word == null)  
  107.             return;  
  108.   
  109.         // 过滤多于空格  
  110.         word = word.trim();  
  111.         // 获取词长  
  112.         int len = word.length();  
  113.         // 初始化二级索引表(首字hash表)  
  114.         if (this.indexTable[len - 1] == null)  
  115.             this.indexTable[len - 1] = new Hashtable
  116.         // 获取词的首字  
  117.         String fch = word.substring(01);  
  118.         // 首字对应的词汇列表  
  119.         ArrayList<string> wal = null;  </string>
  120.         if (this.indexTable[len - 1].containsKey(fch))  
  121.             wal = this.indexTable[len - 1].get(fch);  
  122.         else  
  123.             wal = new ArrayList<string>();  </string>
  124.   
  125.         // 截取剩余部分  
  126.         String str = word.substring(1, len);  
  127.         // 当词汇表中不存在当前词汇时插入新词汇  
  128.         if (Collections.binarySearch(wal, str) < 0)  
  129.             wal.add(str);  
  130.   
  131.         Collections.sort(wal);  
  132.         this.indexTable[len - 1].put(fch, wal);  
  133.     }  
  134.   
  135.     /** 
  136.      * 载入以文本格式存储的词典 
  137.      *  
  138.      * @param fileName 
  139.      *            词典的文件名 
  140.      */  
  141.     @SuppressWarnings("unchecked")  
  142.     public void loadDictionary(String fileName)  
  143.     {  
  144.         try  
  145.         {  
  146.             // 初始化输入流  
  147.             BufferedReader in = new BufferedReader(new FileReader(fileName));  
  148.             String word = null;  
  149.             // 初始化记录链表  
  150.             LinkedList<string> wordLink = new LinkedList<string>();  </string></string>
  151.             // 最大词长  
  152.             this.maxWordLen = 0;  
  153.   
  154.             // 读取词典  
  155.             while ((word = in.readLine()) != null)  
  156.             {  
  157.                 if (word.length() > this.maxWordLen)  
  158.                     this.maxWordLen = word.length();  
  159.                 wordLink.add(word);  
  160.                 this.wordCount++;  
  161.             }  
  162.   
  163.             // 初始化一级索引表(词长索引表)  
  164.             this.indexTable = new Hashtable[this.maxWordLen];  
  165.             // 重新遍历词典链表  
  166.             for (String w : wordLink)  
  167.             {  
  168.                 // 插入词汇  
  169.                 this.insertWord(w);  
  170.             }  
  171.             // 回收资源  
  172.             wordLink.clear();  
  173.         }  
  174.         catch (IOException e)  
  175.         {  
  176.             // TODO 自动生成 catch 块  
  177.             e.printStackTrace();  
  178.         }  
  179.     }  
  180.   
  181.     /** 
  182.      * 判断输入的字符串是否在词典中 
  183.      *  
  184.      * @param word 
  185.      *            待判断字符串 
  186.      * @return 判断结果 
  187.      */  
  188.     public boolean match(String word)  
  189.     {  
  190.         if (word == null)  
  191.             return false;  
  192.   
  193.         // 获取词长  
  194.         int len = word.length();  
  195.   
  196.         // 当词长大于当前词库中最大词长则返回false  
  197.         if (len > this.maxWordLen)  
  198.             return false;  
  199.   
  200.         // 当词长为len的hash索引表未被初始化时返回false  
  201.         if (this.indexTable[len - 1] == null)  
  202.             return false;  
  203.   
  204.         // 获取首字  
  205.         String fch = word.substring(01);  
  206.         if (this.indexTable[len - 1].containsKey(fch))  
  207.         {  
  208.             if (len == 1)  
  209.                 return true;  
  210.             else  
  211.             {  
  212.                 // 获取以fch开头的词汇表  
  213.                 ArrayList<string> wal = this.indexTable[len - 1].get(fch);  </string>
  214.                 // 折半查找  
  215.                 if (Collections.binarySearch(wal, word.substring(1, len)) < 0)  
  216.                     return false;  
  217.                 else  
  218.                     return true;  
  219.             }  
  220.         }  
  221.         else  
  222.             return false;  
  223.     }  
  224.   
  225.     /** 
  226.      * 输出已载入内存中所有词汇 
  227.      *  
  228.      * @param out 
  229.      *            输出流 
  230.      */  
  231.     public void print(PrintStream out)  
  232.     {  
  233.         for (int i = 0; i < this.indexTable.length; i++)  
  234.         {  
  235.             out.println("词长:" + (i + 1));  
  236.             // 判断词典是否已初始化  
  237.             if (this.indexTable[i] != null)  
  238.             {  
  239.                 for (String fch : this.indexTable[i].keySet())  
  240.                 {  
  241.                     out.println("首字:" + fch);  
  242.                     for (String w : this.indexTable[i].get(fch))  
  243.                         out.println("\t" + w);  
  244.                 }  
  245.             }  
  246.         }  
  247.         out.flush();  
  248.     }  
  249. }  
为什么说是双Hash结构呢?因为在查询词汇时,先使用词汇的长度length作为第一次Hash的key取出Hashtable结构的value,接下来也就跟首字Hash查询的操作一样了:取首字作为key取出一维线性表的value后采用折半查找。当词典中词汇数目很大时,一维线性表过长,进行折半查找无疑会提高比较的次数从而降低了效率。而使用双Hash正是希望通过增加多一次Hash求值从而将长的词汇表剪短成为多段较短的一维线性表减低折半查找时的比较次数。

既然说道了序列化,当然少不了序列化操作类DictionaryUtil:
java 代码
 
  1. /* 
  2.  * @作者:Hades , 创建日期:2006-11-18 
  3.  * 
  4.  * 汕头大学03计算机本科 
  5.  *  
  6.  */  
  7. package edu.stu.cn.segment.matching.util;  
  8.   
  9. import java.io.BufferedInputStream;  
  10. import java.io.BufferedOutputStream;  
  11. import java.io.FileInputStream;  
  12. import java.io.FileOutputStream;  
  13. import java.io.IOException;  
  14. import java.io.ObjectInputStream;  
  15. import java.io.ObjectOutputStream;  
  16.   
  17. import edu.stu.cn.segment.matching.dictionary.DictionaryImpl;  
  18.   
  19. /** 
  20.  * @author Hades Guan 词典工具类 
  21.  *  
  22.  */  
  23. public class DictionaryUtilextends DictionaryImpl>  
  24. {  
  25.     /** 
  26.      * 从fileName文件中读入词典实例 
  27.      *  
  28.      * @param fileName 
  29.      *            存储文件 
  30.      * @return 词典实例 
  31.      */  
  32.     @SuppressWarnings("unchecked")  
  33.     public T readDictionary(String fileName)  
  34.     {  
  35.         try  
  36.         {  
  37.             ObjectInputStream in = new ObjectInputStream(  
  38.                     new BufferedInputStream(new FileInputStream(fileName)));  
  39.             T dic = (T) in.readObject();  
  40.             in.close();  
  41.             return dic;  
  42.         }  
  43.         catch (Exception e)  
  44.         {  
  45.             System.err.println(e.getMessage());  
  46.             return null;  
  47.         }  
  48.     }  
  49.   
  50.     /** 
  51.      * 将词典实例dic写入到fileName文件中 
  52.      *  
  53.      * @param dic 
  54.      *            词典实例 
  55.      * @param fileName 
  56.      *            存储文件 
  57.      * @return 操作成功与否 
  58.      */  
  59.     public boolean writeDictionary(T dic, String fileName)  
  60.     {  
  61.         try  
  62.         {  
  63.             ObjectOutputStream out = new ObjectOutputStream(  
  64.                     new BufferedOutputStream(new FileOutputStream(fileName)));  
  65.             out.writeObject(dic);  
  66.             out.flush();  
  67.             out.close();  
  68.             return true;  
  69.         }  
  70.         catch (IOException e)  
  71.         {  
  72.             System.err.println(e.getMessage());  
  73.             return false;  
  74.         }  
  75.   
  76.     }  
  77. }  
通过这个操作类可以把实现DictionaryImpl接口的词典实现类写入文件或者从文件中读出。
分享到:
评论

相关推荐

    Lucene中文分词组件 JE-Analysis 1.5.1

    1.2 —— 2006-06-08 增加中文数字的匹配(如:二零零六) 数量词采用“n”作为数字通配符 优化词典结构以便修改调整 1.1 —— 2006-06-06 增加扩展词典的静态读取方法 1.0.1 —— 2006-06-02 ...

    IKAnalyzer中文分词器V3.1.1使用手册

    最初作为开源项目Lucene的一部分,它主要服务于该搜索引擎框架,通过结合词典分词与语法分析算法实现了中文文本的高效分词。 ##### 1.1 结构设计 - **正向迭代最细粒度切分算法**:这是IKAnalyzer的核心算法之一,...

    Lucene中文分词组件 JE-Analysis 1.4.0

    1.2 —— 2006-06-08 增加中文数字的匹配(如:二零零六) 数量词采用“n”作为数字通配符 优化词典结构以便修改调整 1.1 —— 2006-06-06 增加扩展词典的静态读取方法 1.0.1 —— 2006-06-02 ...

    elasticsearch-analysis-ik-7.16.2.zip

    而在中文处理中,分词器的作用尤为重要,它能将复杂的中文文本拆解为可索引的基本单位——词语。本文将深入探讨Elasticsearch的IK分词器,即elasticsearch-analysis-ik-7.16.2,以及与其相关的依赖库。 **一、...

    elasticsearch-analysis-ik-7.4.0.zip

    标题中的"elasticsearch-analysis-ik-7.4.0.zip"指的是Elasticsearch的一个插件——IK分词器的7.4.0版本。这个插件是为了解决Elasticsearch在处理中文文本时的分词问题,因为Elasticsearch默认的分析器主要针对英文...

    elasticsearch-analysis-ik-5.2.0 分词器 大数据 分析查询

    它的主要功能包括对中文文本进行精确模式和全模式的分词,同时支持自定义扩展词典,能够根据业务需求定制分词规则。版本号 "5.2.0" 表示这是适用于 Elasticsearch 5.2.0 版本的 IK 分词器插件。 在大数据场景下,...

    elasticsearch-analysis-ik-7.3.2.zip

    《Elasticsearch中文分词器IK插件详解》 Elasticsearch(ES)作为一个强大的全文搜索引擎,其在处理中文文档时,对中文分词的准确性和效率有着至关重要的作用。"elasticsearch-analysis-ik"是ES中最受欢迎的中文...

    elasticsearch-analysis-ik-6.8.6.zip

    IK分词器不仅支持常见的中文词汇,还能通过自定义扩展词典进行个性化分词,适应各种应用场景。 在IK分词库的实现中,包含了以下核心组件: 1. **httpclient-4.5.2.jar**:Apache HttpClient库,用于网络通信,分词...

    elasticsearch-analysis-ik-5.2.2

    在处理中文分词方面,Elasticsearch有一个非常重要的插件——IK分词器(Analysis IK)。本文将详细讲解"elasticsearch-analysis-ik-5.2.2"这一版本的IK分词器及其相关组件。 首先,"elasticsearch-analysis-ik-...

    elasticsearch-analysis-ik-6.7.0.zip

    4. **commons-logging-1.2.jar**:Apache Commons Logging,一个轻量级的日志接口,允许在不修改代码的情况下切换日志实现。 5. **elasticsearch-analysis-ik-6.7.0.jar**:IK分词器的核心jar包,负责处理中文分词...

    elasticsearch-analysis-ik-7.3.0.zip

    标题“elasticsearch-analysis-ik-7.3.0.zip”所指的是一款针对Elasticsearch的中文分词插件——IK Analyzer的7.3.0版本。IK Analyzer是一款广泛应用于Elasticsearch和Kibana的中文分词工具,旨在提供高效、灵活的...

    elasticsearch-analysis-ik-6.8.23.zip

    它由开源社区开发并维护,旨在提供更优秀的中文分词效果,支持复杂的分词策略和自定义扩展。该插件的最新版本为6.8.23,与Elasticsearch 6.8.x系列兼容。 分词器在全文搜索中扮演的角色是将文本拆分成一系列可索引...

    最新版windows elasticsearch-analysis-ik-7.13.3.zip

    4. commons-logging-1.2.jar:通用的日志记录接口,为各种日志框架提供统一的接口。 5. elasticsearch-analysis-ik-7.13.3.jar:核心插件文件,包含了IK分词器的实现。 6. plugin-security.policy:插件的安全策略...

    解密搜索引擎技术实战:Lucene&Java精华版

    **第4章**“中文分词原理与实现”详细探讨了中文分词的相关理论和技术实现。这一章节覆盖了中文分词的基本原理、算法实现、分词流程、未登录词识别等多个方面: - **4.1 Lucene中的中文分词**: - **4.1.1 Lucene...

    Text-Mining-2020

    例如,使用NLTK(Natural Language Toolkit)库进行英文文本的预处理,使用jieba进行中文文本的分词。 1.2 信息抽取:通过模式匹配、关键词匹配或基于规则的方法,从文本中提取结构化的信息,如人名、地名、事件等...

    关键词密度分布法在偏重摘要中的应用研究

    随着互联网的迅猛发展,海量信息的出现使得用户面临一个严峻的问题——如何从这些庞杂的信息中快速准确地提取出自己所需的内容。传统的搜索引擎虽然能够帮助用户定位到相关文档,但往往需要用户自行阅读全文以筛选出...

Global site tag (gtag.js) - Google Analytics