中文信息处理文档格式.docx
《中文信息处理文档格式.docx》由会员分享,可在线阅读,更多相关《中文信息处理文档格式.docx(11页珍藏版)》请在冰豆网上搜索。
3.掌握四种分词方法“词典正向最大匹配法、词典逆向最大匹配、基于确定文法的分词法、基于统计的分词方法”。
二.实验环境
Win764位
DEV-C++编译器
三、实验内容与步骤
1、词典正、逆向最大匹配法
2、词典正、逆向最小匹配法
3、邻近匹配
4、最短路径匹配
词典逆向最大匹配法,基本思路是:
1、将词典的每个词条读入内存,最长是4字词,最短是1字词;
2、从语料中读入一段(一行)文字,保存为字符串;
3、如果字符串长度大于4个中文字符,则取字符串最右边的4个中文字符,作为候选词;
否则取出整个字符串作为候选词;
4、在词典中查找这个候选词,如果查找失败,则去掉这个候选词的最左字,重复这步进行查找,直到候选词为1个中文字符;
5、将候选词从字符串中取出、删除,回到第3步直到字符串为空;
6、回到第2步直到语料已读完。
词典正向最大匹配法,基本思路是:
3、如果字符串长度大于4个中文字符,则取字符串最左边的4个中文字符,作为候选词;
4、在词典中查找这个候选词,如果查找失败,则去掉这个候选词的最右字,重复这步进行查找,直到候选词为1个中文字符;
邻近匹配,基本思路是:
1、对于待切分的一段字符串C0C1C2…Cn-1,根据C0C1得到所有以C0C1为首的词条集W,如果词条集为空,则将C0切分出来。
2、否则取满足max{k|C0C1…Ck∈W}的字符串C0C1…Ck切分出来。
3、然后将后面的剩余字符串Ck+1…Cn-1作为新的待切分字符串进行同样的处理,直到待切分串为空为止。
四、实验过程与分析
逆向最大匹配法
源代码:
#include<
iostream>
string>
fstream>
sstream>
ext/hash_map>
iomanip>
stdio.h>
time.h>
#defineMaxWordLength12//最大词长字节(即4个汉字)
#defineSeparator"
"
//词界标记
#defineUTF8_CN_LEN3//汉字的UTF-8编码为3字节
usingnamespacestd;
usingnamespace__gnu_cxx;
namespace__gnu_cxx
{
template<
>
structhash<
std:
:
string>
{
size_toperator()(conststd:
string&
x)const
returnhash<
constchar*>
()(x.c_str());
}
};
}
hash_map<
string,int>
wordhash;
//词典
//读入词典
voidget_dict(void)
stringstrtmp;
//读取词典的每一行
stringword;
//保存每个词
typedefpair<
sipair;
ifstreaminfile("
CoreDict.txt.utf8"
);
if(!
infile.is_open())
cerr<
<
Unabletoopeninputfile:
<
wordlexicon"
--bailingout!
"
endl;
system("
pause"
exit(-1);
while(getline(infile,strtmp))//读入词典的每一行并将其添加入哈希中
istringstreamistr(strtmp);
istr>
word;
//读入每行第一个词
wordhash.insert(sipair(word,1));
//插入到哈希中
infile.close();
//删除语料库中已有的分词空格,由本程序重新分词
stringdel_space(strings1)
intp1=0,p2=0;
intcount;
strings2;
while(p2<
s1.length()){
//删除半角空格
if(s1[p2]==32)
if(p2>
p1)
s2+=s1.substr(p1,p2-p1);
p2++;
p1=p2;
else
returns2;
//用词典做逆向最大匹配法分词
stringdict_segment(strings1)
strings2="
;
//用s2存放分词结果
while(!
s1.empty()){
intlen=(int)s1.length();
//取输入串长度
if(len>
MaxWordLength)//如果输入串长度大于最大词长
len=MaxWordLength;
//只在最大词长范围内进行处理
stringw=s1.substr(s1.length()-len,len);
intn=(wordhash.find(w)!
=wordhash.end());
//在词典中查找相应的词
while(len>
UTF8_CN_LEN&
&
n==0)//如果不是词
len-=UTF8_CN_LEN;
//从候选词左边减掉一个汉字,将剩下的部分作为候选词
w=s1.substr(s1.length()-len,len);
n=(wordhash.find(w)!
w=w+Separator;
s2=w+s2;
s1=s1.substr(0,s1.length()-len);
//中文分词,先分出数字
stringcn_segment(strings1)
//先分出数字和字母
intp1,p2;
p1=p2=0;
while(p2<
=(s1.length()-UTF8_CN_LEN)&
(s1.substr(p2,UTF8_CN_LEN).at(0)<
'
0'
||s1.substr(p2,UTF8_CN_LEN).at(0)>
9'
)){//不是数字或字母
p2+=UTF8_CN_LEN;
s2+=dict_segment(s1.substr(p1,p2-p1));
//之前的句子用词典分词
//将数字和字母分出来
p1=p2;
p2+=3;
(s1.substr(p2,UTF8_CN_LEN).at(0)>
='
s1.substr(p2,UTF8_CN_LEN).at(0)<
)){//是数字或字母
}//endwhile
//在执行中文分词前,过滤半角空格以及其他非UTF-8字符
stringseg_analysis(strings1)
strings3="
intp1=0;
intp2=0;
if(((s1[p2]>
4)&
14)^14){//过滤非utf-8字符
count=0;
do{
count++;
}while((((s1[p2]>
14)^14)&
p2<
s1.length());
s2=s1.substr(p1,p2-count-p1);
//数字前的串
s3+=cn_segment(s2)+s1.substr(p2-count,count)+Separator;
//数字
if(p2<
=s1.length()){//这个等号,当数字是最后一个字符时!
s1=s1.substr(p2,s1.length()-p2);
//剩余串
else
if(p2!
=0){
s3+=cn_segment(s1);
returns3;
};
intmain(intargc,char*argv[])
1998-01-qiefen-file.txt.utf8"
//打开输入文件
infile.is_open())//打开输入文件失败则退出程序
argv[1]<
ofstreamoutfile1("
result.txt.utf8"
//确定输出文件
outfile1.is_open()){
Unabletoopenfile:
SegmentResult.txt"
--bailingout!
}
clock_tstart,finish;
doubleduration;
start=clock();
get_dict();
finish=clock();
duration=(double)(finish-start)/CLOCKS_PER_SEC;
cout<
词典读入完毕,耗时"
duration<
s"
//用于保存从语料库中读入的每一行
stringline;
//用于输出每一行的结果
正在分词并输出到文件,请稍候..."
while(getline(infile,strtmp))//读入语料库中的每一行并用最大匹配法处理
line=del_space(strtmp);
line=seg_analysis(line);
//调用分词函数进行分词处理
outfile1<
line<
//将分词结果写入目标文件
分词完毕,耗时"
s"
分词结果保存在result.txt.utf8中。
return0;
}
邻近匹配
CStringCSeg:
NM(CStrings)
{
CStrswords;
//以w为首的词条集
CStringret="
while(!
s.IsEmpty())
{
words.clear();
CStringw;
intlen=s.GetLength();
if(len<
4)
w=s;
else
{
w=s.Left(4);
//取头两个字
words=myDic.GetWords(w);
//取得以w为首的词条集
intmax=1,k;
for(inti=0;
i<
words.size();
i++)
{
k=words[i].GetLength();
if(s.Left(k)==words[i]&
k>
max)//长度最长且完全匹配
{
w=s.Left(k);
max=k;
}
}
if(myDic.GetWordID(w)==-1)//头两个字不构成词
w=s.Left
(2);
}
ret+=w+SEP;
s=s.Mid(w.GetLength());
returnret;
五、实验总结
中文分词的基本处理是针对输入文字串进行分词、过滤处理,输出中文单词、英文单词和数字串等一系列分割好的字符串。
常用的分词算法有正、逆向最大匹配,正、逆向最小匹配,邻近匹配,最短路径匹配。
实验表明:
对于汉语来说,逆向最大匹配法比最大匹配法更有效。