《自然语言处理导论》中文分词程序实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《自然语言处理导论》
中文分词实验报告
一、实验目的
了解中文分词意义
掌握中文分词的基本方法
二、实验环境
Win7 64位
DEV-C++编译器
三、实验设计
(一)分词策略
目前较为成熟的中文分词方法主要有:
1、词典正向最大匹配法
2、词典逆向最大匹配法
3、基于确定文法的分词法
4、基于统计的分词方法
一般认为,词典的逆向匹配法要优于正向匹配法。基于确定文法和基于统计的方法作为自然语言处理的两个流派,各有千秋。
我设计的是根据词典逆向最大匹配法,基本思路是:
1、将词典的每个词条读入内存,最长是4字词,最短是1字词;
2、从语料中读入一段(一行)文字,保存为字符串;
3、如果字符串长度大于4个中文字符,则取字符串最右边的4个中文字符,作
为候选词;否则取出整个字符串作为候选词;
4、在词典中查找这个候选词,如果查找失败,则去掉这个候选词的最左字,重
复这步进行查找,直到候选词为1个中文字符;
5、将候选词从字符串中取出、删除,回到第3步直到字符串为空;
6、回到第2步直到语料已读完。
(二)程序设计
查找算法:哈希表
汉字编码格式:UTF-8
程序流程图:
源代码:
#include
#include
#include
#include
#include
#include
#include
#include
#define MaxWordLength 12 // 最大词长字节(即4个汉字)
#define Separator " " // 词界标记
#define UTF8_CN_LEN 3 // 汉字的UTF-8编码为3字节
using namespace std;
using namespace __gnu_cxx;
namespace __gnu_cxx
{
template<> struct hash< std::string >
{
size_t operator()( const std::string& x ) const
{
return hash< const char* >()( x.c_str() );
}
};
}
hash_map
//读入词典
void get_dict(void)
{
string strtmp; //读取词典的每一行
string word; //保存每个词
typedef pair
ifstream infile("CoreDict.txt.utf8");
if (!infile.is_open())
{
cerr << "Unable to open input file: " << "wordlexicon"
<< " -- bailing out!" << endl;
system("pause");
exit(-1);
}
while (getline(infile, strtmp)) // 读入词典的每一行并将其添加入哈希中{
istringstream istr(strtmp);
istr >> word; //读入每行第一个词
wordhash.insert(sipair(word, 1)); //插入到哈希中
}
infile.close();
}
//删除语料库中已有的分词空格,由本程序重新分词
string del_space(string s1)
{
int p1=0,p2=0;
int count;
string s2;
while (p2 < s1.length()){
//删除半角空格
if (s1[p2] == 32)
{
if (p2>p1)
s2 += s1.substr(p1,p2-p1);
p2++;
p1=p2;
}
else
{
p2++;
}
}
s2 += s1.substr(p1,p2-p1);
return s2;
}
//用词典做逆向最大匹配法分词
string dict_segment(string s1)
{
string s2 = ""; //用s2存放分词结果
while (!s1.empty()) {
int len = (int) s1.length(); // 取输入串长度
if (len > MaxWordLength) // 如果输入串长度大于最大词长
{
len = MaxWordLength; // 只在最大词长范围内进行处理
string w = s1.substr(s1.length() - len, len);
int n = (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) != wordhash.end());
}
w = w + Separator;
s2 = w + s2;
s1 = s1.substr(0, s1.length() - len);
}
return s2;
}
//中文分词,先分出数字
string cn_segment(string s1)
{
//先分出数字和字母
string s2;
int p1,p2;
p1 = p2 = 0;
while (p2 < s1.length()){
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;
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;