中文分词二级hash词典构造

1.汉字编码

汉字在计算机内部是以内码的形式进行存储的,汉字内码是汉字在汉字信息处理系统中最基本的表达形式,它与汉字交换码、汉字区位码有一定的对应关系。由于自定义编码顺序的特殊性,因而,可通过计算偏移量的方法来定位该汉字在编码表中任意的位置。国标GB2312汉字编码表共收录了6763个汉字。GB2312-80标注规定汉语字符的交换码由两个ASCII码构成:第一个是区码,取值从OxA1OxF7,共87个区,第二个是位码,从OxA10xFE,共94位。区码为OxA10xAE的存储全角符号,如标点、字母等。GB2312-80汉字的编码空间是BOA1-FIFE,共有72 * 94 = 6768个码位,实有6763个汉字,其中一级汉字3755个,接着是5个空位,后面是3008个二级汉字。

汉字在编码表中的偏移量计算公式如下:
offset = (ch1 – 0xB0) * 94 + (ch2 – 0xA1)    (1) [可以用一个72*94的数组实现汉字的一一映射,1标识汉字在词典中存在,0标识不存在]
其中,offset代表某汉字在编码表中的位置,ch1、ch2代表汉字的内部码。

2.二级hash词典构造

2.1hash字典结构

struct Second//二级hash
{
string m_sKey; //字
char cKeyId[9];//编号(根据位置关系编)
bool m_bFlagStop;//是否停止词
Second *next;//相同长度词队列
Second(string k="",bool flag=false,Second *n=NULL):m_sKey(k),m_bFlagStop(flag),next(n)
{}
};

struct Head//首字hash
{
int m_nSize; //当前词最大长度
string m_sKey; //字
char m_cKeyId[9];//编号(根据位置关系编)
bool m_bFagStop;//是否停止词
vector<Second*> Words; //二级hash
Head(string k = "",int s = 0,char *cKey="0",bool flag=false):m_sKey(k),m_bFagStop(flag),m_nSize(s)
{
}
};

2.2首字hash(单字映射)

将GB2312中的所有汉字,用offset = (ch1 – 0xB0) * 94 + (ch2 – 0xA1) 一一映射到一个长度为6763的Head结构vector,首字Hash表中每一项的结构如下,其中Ch

为该汉字,Second是指向二级Hash表的指针。

2.2长度hash

对于不同的首字来说,以其开头的词不仅数量变化很大,而且没有明显的特征规律。如果想要只通过首字Hash表进行查找不仅需要多次比较,而且不容易找出最长的词条。为了减少查询、比较次数,同时最精确的找出最长词条,本文对以某个字开头的所有词的长度进行第二次Hash,将以某个字开头的所有词条散列在不同的队列上,比如以“电”开头的所有词条电影、电视、电路、电视迷、电视网、电视机、电视公司、电视直播、电视接收、电算中心、电视接收机,会被散列到二字词、三自词、四字词、五字词这四个队列上。这样增加了队列个数,减少了队列长度,不仅提高了查询命中率,而且由于最长词条的长度是已知的,所以能极大提高最长匹配分词的效率。

2.3词条队列

词条队列包含一组首字相同、长度相同的词条。一个词的首字和长度决定了它所在的词条队列,因此当查询一个词是否在现有词典中时最终变成查询该词是否存在于特定的词条队列里。词条队列的结构如下,其中k为该词条队列的长度,word1,word2,word3…wordk为K个词条。队列中的词条根据词典排序规则进行升序排列。

3.中文分词方法

常用的有正向最大匹配和逆向最大匹配,统计结果表明单纯使用正向最大匹配错误率为1/169,单纯使用逆向最大匹配错误率1/245,逆向最大匹配会稍好一些。

参考:http://wenku.baidu.com/view/4184f769af1ffc4ffe47acba.html

原文地址:https://www.cnblogs.com/siliconvalley/p/3120628.html