字符串匹配的分词.docx
- 文档编号:11671090
- 上传时间:2023-03-30
- 格式:DOCX
- 页数:10
- 大小:23.74KB
字符串匹配的分词.docx
《字符串匹配的分词.docx》由会员分享,可在线阅读,更多相关《字符串匹配的分词.docx(10页珍藏版)》请在冰豆网上搜索。
字符串匹配的分词
竭诚为您提供优质文档/双击可除
字符串匹配的分词
篇一:
中文分词入门之最大匹配法
中文分词入门之最大匹配法
发表于20XX年01月12号由52nlp
中文分词在中文信息处理中是最最基础的,无论机器翻译亦或信息检索还是其他相关应用,如果涉及中文,都离不开中文分词,因此中文分词具有极高的地位。
中文分词入门最简单应该是最大匹配法了,当年师兄布置给我的第一个学习任务就是实现最大匹配法的分词算法(正向、逆向)。
记得当时对自己参考学习最有帮助的是北大詹卫东老师“中文信息处理基础”的课件和源程序,不过他实现的是mfc程序,词表存储在数据库里。
自己实现时用纯c++实现,利用hash_map存储词表。
这里我介绍一下相关的知识和一个简单的程序示例,部分参考自詹老师的讲义。
正向最大匹配法算法如下所示:
(注:
以上最大匹配算法图来自于詹老师讲义)
逆向匹配法思想与正向一样,只是从右向左切分,这里举一个例子:
输入例句:
s1=”计算语言学课程有意思”;
定义:
最大词长maxLen=5;s2=”“;分隔符=“/”;
假设存在词表:
…,计算语言学,课程,意思,…;
最大逆向匹配分词算法过程如下:
(1)s2=”";s1不为空,从s1右边取出候选子串w=”课程有意思”;
(2)查词表,w不在词表中,将w最左边一个字去掉,得到w=”程有意思”;
(3)查词表,w不在词表中,将w最左边一个字去掉,得到w=”有意思”;
(4)查词表,w不在词表中,将w最左边一个字去掉,得到w=”意思”
(5)查词表,“意思”在词表中,将w加入到s2中,s2=”意思/”,并将w从s1中去掉,此时s1=”计算语言学课程有”;
(6)s1不为空,于是从s1左边取出候选子串w=”言学课程有”;
(7)查词表,w不在词表中,将w最左边一个字去掉,得到w=”学课程有”;
(8)查词表,w不在词表中,将w最左边一个字去掉,得到w=”课程有”;
(9)查词表,w不在词表中,将w最左边一个字去掉,得到w=”程有”;
(10)查词表,w不在词表中,将w最左边一个字去掉,得到w=”有”,这w是单字,将w加入到s2中,s2=“/有/意思”,并将w从s1中去掉,此时s1=”计算语言学课程”;
(11)s1不为空,于是从s1左边取出候选子串w=”语言学课程”;
(12)查词表,w不在词表中,将w最左边一个字去掉,得到w=”言学课程”;
(13)查词表,w不在词表中,将w最左边一个字去掉,得到w=”学课程”;
(14)查词表,w不在词表中,将w最左边一个字去掉,得到w=”课程”;
(15)查词表,“意思”在词表中,将w加入到s2中,s2=“课程/有/意思/”,并将w从s1中去掉,此时s1=”计算语言学”;
(16)s1不为空,于是从s1左边取出候选子串w=”计算语言学”;
(17)查词表,“计算语言学”在词表中,将w加入到s2中,s2=“计算语言学/课程/有/意思/”,并将w从s1中去掉,此时s1=”";
(18)s1为空,输出s2作为分词结果,分词过程结束。
相应程序示例:
准备文件:
建立一个词表文件wordlexicon,格式如下
计算语言学
课程
意思
输入文件:
test,格式如下
计算语言学课程有意思
编译后执行如下:
segword.exetest
输出分词结果文件:
segmentResult.txt
源代码如下:
//Dictionary.h
#include
#include
#include
#include
#include
usingnamespacestd;
usingnamespacestdext;
classcDictionary
{
public:
cDictionary();//将词典文件读入并构造为一个哈希词典
~cDictionary();
intFindword(stringw);//在哈希词典中查找词
private:
stringstrtmp;//读取词典的每一行
stringword;//保存每个词
hash_mapwordhash;//用于读取词典后的哈希
hash_map:
:
iteratorworditer;//
typedefpairsipair;
};
//将词典文件读入并构造为一个哈希词典
cDictionary:
:
cDictionary()
{
ifstreaminfile(“wordlexicon”);//打开词典
if(!
infile.is_open())//打开词典失败则退出程序
{
cerr exit(-1);
}
while(getline(infile,strtmp,n))//读入词典的每一行并将其添加入哈希中
{
istringstreamistr(strtmp);
istr>>word;//读入每行第一个词
wordhash.insert(sipair(word,1));//插入到哈希中
}
}
cDictionary:
:
~cDictionary()
{
}
//在哈希词典中查找词,若找到,则返回,否则返回
intcDictionary:
:
Findword(stringw)
{
if(wordhash.find(w)!
=wordhash.end())
{
return1;
}
else
{
return0;
}
}
//主程序main.cpp
#include“Dictionary.h”
#definemaxwordLength10//最大词长为个字节(即个汉字)
#defineseparator“/”//词界标记
cDictionarywordDic;//初始化一个词典
//对字符串用最大匹配法(正向或逆向)处理
stringsegmentsentence(strings1)
{
strings2=“”;//用s2存放分词结果
while(!
s1.empty())
{
intlen=(int)s1.length();//取输入串长度
if(len>maxwordLength)//如果输入串长度大于最大词长
{
len=maxwordLength;//只在最大词长范围内进行处理
}
//stringw=s1.substr(0,len);//(正向用)将输入串左边等于最大词长长度串取出作为候选词stringw=s1.substr(s1.length()–len,len);//逆向用
intn=wordDic.Findword(w);//在词典中查找相应的词
while(len>2//从候选词右边减掉一个汉字,将剩下的部分作为候选词
//w=w.substr(0,len);//正向用
w=s1.substr(s1.length()–len,len);//逆向用
n=wordDic.Findword(w);
}
//s2+=w+separator;//(正向用)将匹配得到的词连同词界标记加到输出串末尾
w=w+separator;//(逆向用)
s2=w+s2;//(逆向用)
//s1=s1.substr(w.length(),s1.length());//(正向用)从s1-w处开始
s1=s1.substr(0,s1.length()–len);//(逆向用)
}
returns2;
}
//对句子进行最大匹配法处理,包含对特殊字符的处理
stringsegmentsentencemm(strings1)
{
strings2=“”;//用s2存放分词结果
inti;
intdd;
while(!
s1.empty())
{
unsignedcharch=(unsignedchar)s1[0];
if(ch {
i=1;
dd=(int)s1.length();
while(i }
if((ch!
=32)
}
else
{
//if(ch==10||ch==13)//如果是换行或回车符,将它拷贝给s2输出
if(ch==10||ch==13||ch==32)//谢谢读者mces89的指正
{
s2+=s1.substr(0,i);
}
}
s1=s1.substr(i,dd);
continue;
}
else
{
if(ch {
i=0;
dd=(int)s1.length();
while(i 1)正向最大匹配法(由左到右的方向);
2)逆向最大匹配法(由右到左的方向);
3)最少切分(使每一句中切出的词数最小)。
还可以将上述各种方法相互组合,例如,可以将正向最大匹配方法和逆向最大匹配方法结合起来构成双向匹配法。
由于汉语单字成词的特点,正向最小匹配和逆向最小匹配一般很少使用。
一般说来,逆向匹配的切分精度略高于正向匹配,遇到的歧义现象也较少。
统计结果表明,单纯使用正向最大匹配的错误率为1/169,单纯使用逆向最大匹配的错误率为1/245。
但这种精度还远远不能满足实际的需要。
实际使用的分词系统,都是把机械分词作为一种初分手段,还需通过利用各种其它的语言信息来进一步提高切分的准确率。
一种方法是改进扫描方式,称为特征扫描或标志切分,优先在待分析字符串中识别和切分出一些带有明显特征的词,以这些词作为断点,可将原字符串分为较小的串再来进机械分词,从而减少匹配的错误率。
另一种方法是将分词和词类标注结合起来,利用丰富的词类信息对分词决策提供帮助,并且在标注过程中又反过来对分词结果进行检验、调整,从而极大地提高切分的准确率。
2、基于理解的分词方法
这种分词方法是通过让计算机模拟人对句子的理解,达到识别词的效果。
其基本思想就是在分词的同时进行句法、语义分析,利用句法信息和语义信息来处理歧义现象。
它通常包括三个部分:
分词子系统、句法语义子系统、总控部分。
在总控部分的协调下,分词子系统可以获得有关词、句子等的句法和语义信息来对分词歧义进行判断,即它模拟了人对句子的
理解过程。
这种分词方法需要使用大量的语言知识和信息。
由于汉语语言知识的笼统、复杂性,难以将各种语言信息组织成机器可直接读取的形式,因此目前基于理解的分词系统还处在试验阶段。
3、基于统计的分词方法
从形式上看,词是稳定的字的组合,因此在上下文中,相邻的字同时出现的次数越多,就越有可能构成一个词。
因此字与字相邻共现的频率或概率能够较好的反映成词的可信度。
可以对语料中相邻共现的各个字的组合的频度进行统计,计算它们的互现信息。
定义两个字的互现信息,计算两个汉字x、Y的相邻共现概率。
互现信息体现了汉字之间结合关系的紧密程度。
当紧密程度高于某一个阈值时,便可认为此字组可能构成了一个词。
这种方法只需对语料中的字组频度进行统计,不需要切分词典,因而又叫做无词典分词法或统计取词方法。
但这种方法也有一定的局限性,会经常抽出一些共现频度高、但并不是词的常用字组,例如“这一”、“之一”、“有的”、“我的”、“许多的”等,并且对常用词的识别精度差,时空开销大。
实际应用的统计分词系统都要使用一部基本的分词词典(常用词词典)进行串匹配分词,同时使用统计方法识别一些新的词,即将串频统计和串匹配结合起来,既发挥匹配分词切分速度快、效率高的特点,又利用了无词典分词结合上下文识别生词、自动消除歧义的优点。
分词几点要注意:
1.分词算法的时间性能要比较高。
尤其是现在的web搜索,实时性要求很高。
所以作为中文信息处理基础的分词首先必须占用尽可能少的时间。
2.分词正确率的提高并不一定带来检索性能的提高。
分词到达一定精度之后,对中文信息检索的影响不再会很明显,虽然仍然还是有一些影响,但是这已经不是cIR的性能瓶颈。
所以片面的一味追求高准确率的分词算法并不是很适合大规模中文信息检索。
在时间和精度之间存在矛盾无法兼顾的情况下,我们需要在二者之间找到一个合适的平衡点。
3.切分的颗粒度仍然可以依照长词优先准则,但是需要在查询扩展层面进行相关后续处理。
在信息检索中,分词算法只需要集中精力考虑如何消除交叉歧义。
对于覆盖歧义,我们可以利用词典的二次索引和查询扩展来解决。
4.未登录词识别的准确率要比召回率更加重要。
要尽量保证未登录词识别时不进行错误结合,避免因此切分出错误的未登录词。
如果将单字错误的结合成未登录词了,则有可能导致无法正确检索到相应的文档。
XX的分词
首先根据分割符号将查询分开。
“信息检索理论工具”分词后。
然后看看是否有重复的字符串,如果有,就抛弃多余的,只保留一个。
“理论工具理论”分词后,googLe不考虑这个并归计算。
接着判断是否有英文或者数字,如果有的话,把英文或者数字当作一个整体保留并把前后的中文切开。
查询”电影bT下载”分词后。
如果字符串只包含小于等于3个中文字符的话,那就保留不动,当字符串长度大于4个中文字符的时候,XX的分词程序才出马大干快上,把这个字符串肢解掉。
分词算法类型正向最大匹配,反向最大匹配,双向最大匹配,语言模型方法,最短路径算法判断一个分词系统好不好,关键看两点,一个是消除歧义能力;一个是词典未登录词的识别比如人名,地名,机构名等。
XX分词采取了至少两个词典,一个是普通词典,一个是专用词典(人名、地名、新词等)。
而且是专用词典先切分,然后将剩余的片断交由普通词典来切分。
XX用分词算法类型采用的是双向最大匹配算法。
例子:
查询“毛泽东北京华烟云”,XX的分词结果:
”毛泽东/北/京华烟云”
XX分词可以识别人名,也可以识别”京华烟云”,这说明有词典未登录词的识别的功能
首先查询专用词典(人名,部分地名等),将专有名称切出,剩下的部分采取双向分词策略,如果两者(正向最大匹配,反向最大匹配)切分结果相同,说明没有歧义,直接输出分词结果。
如果不一致,则输出最短路径的那个结果,也就是切分的片断越少越好,比如和相比选择后者,和相比选择后者。
如果长度相同,则选择单字词少的那一组切分结果。
“遥远古古巴比伦”,这个查询被XX切分为,而不是切分为”遥/远古/古巴比伦”
如果单字也相同,则选择正向分词结果。
查询“王强大小:
”,XX将其切分为“王/强大/小”,而不是反向切分为“王/强/大小”
XX一直宣传自己在中文处理方面的优势,从上面看,分词算法并无特殊之处,消歧效果并不理想,即使XX采取比上述分词算法复杂些的算法也难以说成是优势,如果说XX有优势的话,唯一的优势就是那个很大的专用词典,这个专用词典登录了人名(比如大长今),称谓(比如老太太),部分地名(比如阿联酋等),估计XX采用学术界公布的比较新的命名实体识别算法从语料库里面不断识别出词典未登录词,逐渐扩充这个专门词典
篇三:
作业三最大匹配分词法
作业三中文分词法
中文分词法:
开始没有思路,后来查了下资料和问了下同学,才搞定的。
我的思路:
这里说的是最大匹配分词法:
首先准备一个分词词表input.txt作为输入,顺序扫描待分词的句子,将句中候选词按照词长从大到小的顺序依次跟词表cizu.txt文件中的词进行匹配,匹配成功即作为一个词输出。
这样就使得每次输出的词是长度最大的(相比已知的确定的词表而言)。
如果一个句中的多字候选词跟词表中所有的词都匹配不上,自然就只能把单字词当作分词结果输出了。
把事先准备好的欲分词文件在目录d:
\\output\\input.txt
,那么我们开始执行程序显示
之后再看文件夹d:
\\output里面多了个output.txt的文件,这就是对input.txt做好的分词输出文件。
程序的算法思想:
首先对一篇文本按照标点符号等自身的分隔符分解成句子,然后对每个句子按照词长mAx_cwoRD_Len=18(9个汉字)的正向最大匹配法进行分词。
在划分句子的时候,最关键的操作在确定字串在何处断开成为独立的句子。
这里考虑了英文和中文混杂的情况。
数据结构:
使用二维的指针数组进行词典存储:
词典中的每个词利用其第一个字节和最后一个字节进行二维定位来存储,有相同的第一个字节和最后一个字节的多个词串用指针进行相连。
这种存储方式极大得提高了查词典的效率,在匹配词串时利用第一字节和最后一个字节直接定位或者通过几级指针快速检索。
输入文本文件和输出文本文件都用一维数组进行存储,对空间的要求比较大,避免了多次文件的I/o操作。
主要文件有测试文件input.txt,输出文件output.txt,这里还有一个字典,就是每个词后面都有可能出现的词语,比如:
人名,人民,人生···等ziguang.txt。
实现的部分源程序如下:
//不进行索引的单词
char*arrayenglishstop[]={
"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
"1","2","3","4","5","6","7","8","9","0",
"about","above","after","again","all","also","am","an","and","any","are","as","at","back","be","been","before","behind","being","below","but","by",
"can","click","do","does","done","each","else","etc","ever","every",
"few","for","from","generally","get","go","gone","has","have","hello","here","how","if","in","into","is","just","keep","later","let","like","lot","lots","made",
"make","makes","many","may","me","more","most","much","must","my","need","no","not",
"now","of","often","on","only","or","other","others","our","out","over","please","put","so","some","such","than","that","the","their","them","then","there","these","they","this","try","to","up","us","very","want","was","we","well","what","when","where","which","why","will","with","within","you","your","yourself"
};
//词典索引时,字或词不需要索引
char*arraychinesestop[]={
"的","吗","么","啊","说","对","在","和","是",
"被","最","所","那","这","有","将","会","与",
"於","于","他","她","它","您","为","欢迎"
};
//标点符号及汉字的标点符号,注意+-"这三个符号,因为在搜索的时候需要通过他们进行异或等条件判断
chararrayAsciisymbol[]={
!
\\,*,(,),-,_,+,=,{,},[,],:
;,\,\",,,,.,?
/,|,@,#,$,%,^,};
//汉字词典
typedefstruct_woRD_noDe
{
charstrword[mAx_cwoRD_Len+1];
//todo,可以增加两个字,三个字,四个字,五个字的数组,这样查起来更快struct_woRD_noDe*nextword;
}woRD_noDe;//定义结构体类型
struct_ch_DIcT{
woRD_noDe*lstwo(本文来自:
博旭范文网:
字符串匹配的分词)rd;
}ch_DIcT[mAx_cDIm][mAx_cDIm];//定义结构体二维数组变量:
词典
charseg_LIsT[mAx_woRD];//定义数组存放分词后的句串
intwnum_In=0;
intwnum_ouT=0;
char*strTrim(charstr[]){
intfirstchar=0;
intendpos=0;
inti;
intfirstpos=0;
for(i=0;str[i]!
=\0;i++){
if(str[i]==||str[i]==\r||str[i]==\n||str[i]==\t){
if(firstchar==0)firstpos++;}
else{endpos=i;
firstchar=1;}}
for(i=firstpos;i str[i-firstpos]=str[i];//去除待处理字符串中的空格、换行等
str[i-firstpos]=\0;
returnstr;}
intaddDictword(char*strword,intlen){
unsignedcharfirstchar,lastchar;
woRD_noDe*curLst;
woRD_noDe*newword,*curTmp;
firstchar=strword[0];
lastchar=strword[len-1];
if(firstchar newword=(woRD_noDe*)malloc(sizeof(woRD_noDe));
if(newword==nuLL)
return-1;
strcpy(newword->strword,strword);
newword->nextword=nuLL;
firstchar-=161;
lastchar-=161;//按词串第一个字节和最后一个字节顺序来存词
curLst=ch_DIcT[firstchar][lastchar].lstword;
if(curLst==nuLL)//reinitlist;{
ch_DIcT[firstchar][lastchar].lstword=newword;
return0;}
curTmp=curLst;//curLst对应位置上已经存词则顺着指针向后找
while(curTmp->nextword!
=nuLL){
curTmp=curTmp->nextword;}
curTmp->nextwor
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 字符串 匹配 分词