⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmwordseg.cpp

📁 利用最大匹配法进行汉语句子的分词 最大匹配算法是最常用的分词算法
💻 CPP
字号:
#include "stdafx.h"
#include "MyDictionary.h"
#include "MMWordSeg.h"
#include "MyFileApp.h"

# define MaxWordLength 8  // 最大词长为8个字节(即4个汉字)
# define Separator "/  "    // 词界标记

CMyDictionary pDict; // 定义一个词典类对象,全局变量

CString SegmentHzStrMM (CString s1)
{// 对一个字符串进行最大匹配法分词的函数

	CString s2="";  // 用s2存放分词结果
	while(!s1.IsEmpty()) { // 如果输入不为空
		int len=s1.GetLength(); // 取输入串长度
		if (len>MaxWordLength)  // 如果输入串长度大于最大词长
			len=MaxWordLength;  // 只在最大词长范围内进行处理

		CString w=s1.Left(len); // 将输入串左边等于最大词长长度串取出作为候选词
		int n=pDict.GetFreq(w);
		
		while(len>2 && n==-1) { // 如果不是词
			len-=2; // 从候选词右边减掉一个汉字,将剩下的部分作为候选词
			w=w.Left(len);
			n=pDict.GetFreq(w);
		}
		s2 += w + Separator; // 将匹配得到的词连同词界标记加到输出串末尾
/*		
		CString tag=""; // 词性标记
		tag=pDict.GetTagOfWord(w); // 从词典中取该词的词性标记
		s2 += w+Separator+tag+" ";  // 将得到的分词结果连同该词的词性标记加上词界符号作为输出
*/
		s1 = s1.Mid(w.GetLength());
	}
	return s2;
}


CString SegmentSentenceMM (CString s1)  
{// 对句子进行分词处理的函数
	CString s2="";
	int i,dd;
	while(!s1.IsEmpty()) {
		unsigned char ch=(unsigned char) s1[0];
		if(ch<128) { // 处理西文字符
			i=1;
			dd=s1.GetLength();
			while(i<dd && ((unsigned char)s1[i]<128) && (s1[i]!=10) && (s1[i]!=13)) // s1[i]不能是换行符或回车符
				i++;
			if ((ch!=32) && (ch!=10) && (ch!=13)) // 如果不是西文空格或换行或回车符
				s2 += s1.Left(i) + Separator;
			else {
				if (ch==10 || ch==13)   // 如果是换行或回车符,将它拷贝给s2输出
					s2+=s1.Left(i);
			}
			s1=s1.Mid(i);
			continue;
		}
		else { 
			if (ch<176) { // 中文标点等非汉字字符
				i=0;
				dd=s1.GetLength();
				while(i<dd && ((unsigned char)s1[i]<176) && ((unsigned char)s1[i]>=161)
							&& (!((unsigned char)s1[i]==161 && ((unsigned char)s1[i+1]>=162 && (unsigned char)s1[i+1]<=168)))
							&& (!((unsigned char)s1[i]==161 && ((unsigned char)s1[i+1]>=171 && (unsigned char)s1[i+1]<=191)))
							&& (!((unsigned char)s1[i]==163 && ((unsigned char)s1[i+1]==172 || (unsigned char)s1[i+1]==161) 
							|| (unsigned char)s1[i+1]==168 || (unsigned char)s1[i+1]==169 || (unsigned char)s1[i+1]==186
							|| (unsigned char)s1[i+1]==187 || (unsigned char)s1[i+1]==191))) // 
					i=i+2; // 假定没有半个汉字
				if (i==0)
					i=i+2;
				if (!(ch==161 && (unsigned char)s1[1]==161)) // 不处理中文空格
					s2+=s1.Left(i) + Separator; // 其他的非汉字双字节字符可能连续输出
				s1=s1.Mid(i);
				continue;
			}
		}
		
		// 以下处理汉字串

		i=2;
		dd=s1.GetLength();
		while(i<dd && (unsigned char)s1[i]>=176) 
//		while(i<dd && (unsigned char)s1[i]>=128 && (unsigned char)s1[i]!=161)
			i+=2;
		
		s2+=SegmentHzStrMM(s1.Left(i));
		s1=s1.Mid(i);
	}

	// 以下程序用于将表示时间的单位合并成一个分词单位

	int TmpPos;
	const char * p;
	CString s2_part_1;
	
	if (s2.Find("  年/")>=0) {
		TmpPos=s2.Find("  年/");
		s2_part_1=s2.Mid(0,TmpPos);
		p=(LPCTSTR) s2_part_1;
		p=p+TmpPos-2;
		if (p[0]=='1'||p[0]=='2'||p[0]=='3'||p[0]=='4'||p[0]=='5'||p[0]=='6'||p[0]=='7'||p[0]=='8'||p[0]=='9'||p[0]=='0') {
			s2_part_1=s2_part_1.Mid(0,TmpPos-1);
			s2=s2_part_1+s2.Mid(TmpPos+2);
		}
	}
	
	if (s2.Find("  月/")>=0) {
		TmpPos=s2.Find("  月/");
		s2_part_1=s2.Mid(0,TmpPos);
		p=(LPCTSTR) s2_part_1;
		p=p+TmpPos-2;
		if (p[0]=='1'||p[0]=='2'||p[0]=='3'||p[0]=='4'||p[0]=='5'||p[0]=='6'||p[0]=='7'||p[0]=='8'||p[0]=='9'||p[0]=='0') {
			s2_part_1=s2_part_1.Mid(0,TmpPos-1);
			s2=s2_part_1+s2.Mid(TmpPos+2);
		}
	}

	if (s2.Find("  日/")>=0) {
		TmpPos=s2.Find("  日/");
		s2_part_1=s2.Mid(0,TmpPos);
		p=(LPCTSTR) s2_part_1;
		p=p+TmpPos-2;
		if (p[0]=='1'||p[0]=='2'||p[0]=='3'||p[0]=='4'||p[0]=='5'||p[0]=='6'||p[0]=='7'||p[0]=='8'||p[0]=='9'||p[0]=='0') {
			s2_part_1=s2_part_1.Mid(0,TmpPos-1);
			s2=s2_part_1+s2.Mid(TmpPos+2);
		}
	}

	return s2;
}

void SegmentAFileMM (CString FileName)
{  // 对文件进行分词处理的函数
	if (pDict.myDatabaseName.IsEmpty()) {
		AfxMessageBox("您没有打开词库,无法进行分词处理");
		if(pDict.OpenMDB()==FALSE)
			return;
	}

	FILE * in, * out;
	in = fopen((const char*) FileName,"rt");
	if(in==NULL) {
		AfxMessageBox("无法打开文件");
		return;
	}
	FileName=ChangeFileName(FileName,"-seg");
	out = fopen((const char*) FileName,"wt");
	if(out==NULL) {
		AfxMessageBox("无法创建文件");
		fclose(in);
		return;
	}

	CStdioFile inFile(in),outFile(out);

	char s[2048];
	CString line;

	while(inFile.ReadString(s,2048)) {// 循环读入文件中的每一行
		line = s;
		line = SegmentSentenceMM(line); // 调用句子分词函数进行分词处理
		outFile.WriteString(line); // 将分词结果写入目标文件
	}
	inFile.Close();
	outFile.Close();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -