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

📄 mydictionary.cpp

📁 最大概率分词法,这种分词算法能够较好的解决汉语分词中的歧义问题,但分词效率比最大匹配分词算法要低
💻 CPP
字号:
#include "stdafx.h"
#include "MyDictionary.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// # define MaxWordLength 8  // 最大词长为8个字节(即4个汉字)

extern int MaxWordLength; // 最大词长由用户在.ini文件中指定

/////////////////////////////////////////////////////////////////////////////
// CWordTagSet

IMPLEMENT_DYNAMIC(CWordTagSet, CDaoRecordset)

CWordTagSet::CWordTagSet(CDaoDatabase* pdb)
	: CDaoRecordset(pdb)
{
	//{{AFX_FIELD_INIT(CWordTagSet)
	m_wid = 0;
	m_pos = _T("");
	m_pfreq = 0;
	m_pid = 0;
	m_word = _T("");
	m_wfreq = 0;
	m_wid2 = 0;
	m_nFields = 7;
	//}}AFX_FIELD_INIT
	m_nDefaultType = dbOpenSnapshot;
	m_WordParam=""; // 给词语参数赋值
	m_TagParam="";  // 给词性标记参数赋值
	m_nParams = 2;  // 参数个数为2
}

/*
CString CWordTagSet::GetDefaultDBName()
{
	return _T("Lexicon.mdb");
}

CString CWordTagSet::GetDefaultSQL()
{
	return _T("[poss],[words]");
}
*/
void CWordTagSet::DoFieldExchange(CDaoFieldExchange* pFX)
{
	//{{AFX_FIELD_MAP(CWordTagSet)
	pFX->SetFieldType(CDaoFieldExchange::param);
	DFX_Text(pFX,"wordParam",m_WordParam);
	DFX_Text(pFX,"tagParam",m_TagParam);
	pFX->SetFieldType(CDaoFieldExchange::outputColumn);
	DFX_Long(pFX, _T("[poss].[wid]"), m_wid);
	DFX_Text(pFX, _T("[pos]"), m_pos);
	DFX_Long(pFX, _T("[pfreq]"), m_pfreq);
	DFX_Long(pFX, _T("[pid]"), m_pid);
	DFX_Text(pFX, _T("[word]"), m_word);
	DFX_Long(pFX, _T("[wfreq]"), m_wfreq);
	DFX_Long(pFX, _T("[words].[wid]"), m_wid2);
	//}}AFX_FIELD_MAP
}

/////////////////////////////////////////////////////////////////////////////
// CWordTagSet diagnostics

#ifdef _DEBUG
void CWordTagSet::AssertValid() const
{
	CDaoRecordset::AssertValid();
}

void CWordTagSet::Dump(CDumpContext& dc) const
{
	CDaoRecordset::Dump(dc);
}
#endif //_DEBUG

int CWordTagSet::GetFreq(CString w, CString t)
{
	// 参量赋值
	m_WordParam=w;
	m_TagParam=t;
	
	// 设置查询条件

	m_strFilter="words.wid=poss.wid AND word=wordParam AND pos=tagParam";
	
	// 执行查询

	Requery();
	
	if(GetRecordCount()==0)
		return -1;
	else
		return m_pfreq;  // 返回该词语在这一词性标记下的出现次数
}

int CWordTagSet::GetFreqs(CString w, CObArray &a)
{// 第二个参数是动态数组,存放查询到的标记及其出现次数
	m_WordParam=w; // 只给一个参数变量赋值

	m_strFilter="words.wid=poss.wid AND word=wordParam";

	Requery();
	if(GetRecordCount()==0)
		return 0;
	for(int i=0;i<a.GetSize();i++)
		if (a[i])
			delete a[i];
	a.RemoveAll();
	i=0;
	CTagFreq * tf;
	while(!IsEOF()) {
		tf=new CTagFreq(m_pos,m_pfreq);
		a.Add(tf);
		i++;
		MoveNext();
	}
	return i;
}

///////////////////////////////////////////////
///////////////////////////////////////////////
// CMyDictionary 类成员函数定义

BOOL CMyDictionary :: OpenMDB()
{//打开词语表,词性标记表

	if (myDatabaseName.IsEmpty()) {
		CFileDialog dlg(TRUE, "mdb", "*.mdb",OFN_OVERWRITEPROMPT);
		if (dlg.DoModal()!=IDOK) { 
			AfxMessageBox("您没有打开词库");
			return FALSE;
		}
      myDatabaseName = dlg.GetPathName();
    }
	
	if(pDatabase)
		return FALSE;

	pDatabase=new CDaoDatabase;
	pDatabase->Open(myDatabaseName);

	pWordsDef=new CDaoTableDef(pDatabase);
	pWordsDef->Open("words"); // 打开词表结构,用词表名words作为参数
	pWords=new CDaoRecordset(pDatabase);
	pWords->Open(pWordsDef); // 打开词表记录集,用词表结构指针作为参数

	pTagsDef=new CDaoTableDef(pDatabase);
	pTagsDef->Open("poss"); // 打开词性表结构,用词性表名poss作为参数
	pTags=new CDaoRecordset(pDatabase);
	pTags->Open(pTagsDef); // 打开词性表记录集,用词性表结构指针作为参数
	
	return TRUE;
}

BOOL CMyDictionary :: CloseMDB()
{// 构析函数,关闭词语表,词性标记表,中文姓名表
	if(pWords) {
		pWords->Close();
		delete pWords;
	}

	if(pTags) {
		pTags->Close();
		delete pTags;
	}
	if(pWordsDef) {
		pWordsDef->Close();
		delete pWordsDef;
	}
	if(pTagsDef) {
		pTagsDef->Close();
		delete pTagsDef;
	}
	if(pDatabase) {
		pDatabase->Close();
		delete pDatabase;
		AfxDaoTerm(); // can now safely terminate DAO
	}
	else
		return FALSE;

	myDatabaseName = "";
	return TRUE;
}

long CMyDictionary :: GetWordID(CString w)
{
	COleVariant kw(w,VT_BSTRT),kwi;
	pWords->SetCurrentIndex("word");
	if(pWords->Seek("=",&kw)) {
		kwi=pWords->GetFieldValue("wid");
		return kwi.lVal;
	}
	else 
		return -1;
}

long CMyDictionary::GetFreq(CString w)
{
	COleVariant kw(w,VT_BSTRT),kf;
	pWords->SetCurrentIndex("word");
	if(pWords->Seek("=",&kw)) {
		kf=pWords->GetFieldValue("wfreq");
		return kf.lVal;
	}
	else return -1;
}


long CMyDictionary::GetFreq(CString w, CString t)
{// 查找某词以某标记出现的次数
	long i=GetWordID(w); // 从词语words表中取词语标识号
	if(i==-1)  // 没有这个词
		return 0;
	COleVariant kwi(i,VT_I4),kt,kf;
	pTags->SetCurrentIndex("wid");
	if(!pTags->Seek("=",&kwi))
		return 0;
	while(!pTags->IsEOF())
	{ // 如果在词性表poss中找到了词语标识号
		kwi = pTags->GetFieldValue("wid"); // 取词性表poss中的当前记录的词语代号值
		if(kwi.lVal != i) // 如果当前记录的wid值发生变化,表示已经不是正在查找的词,则终止查询
			break; 
		
		kt=pTags->GetFieldValue("pos"); // 取当前记录的词性标记值
		if(!strcmp((const char *)kt.pbVal,(const char*)t)) { // 找到词性标记吻合的记录
			kf=pTags->GetFieldValue("pfreq"); // 取当前记录的频次值
			return kf.lVal;
		}
		pTags->MoveNext(); // 移动记录指针到下一条记录
	}
	return -1; // 没有找到词性标记吻合的记录,返回-1
}


long CMyDictionary::GetFreq(CString w, CObArray & a)
{// 查找一个词语在词典中的所有词性标记的出现次数
	long i;
	for(i=0;i<a.GetSize();i++)
		delete a[i];
	a.RemoveAll();
	i=GetWordID(w);
	if(i==-1)
		return 0;
	pTags->SetCurrentIndex("wid");
	CTagFreq * p;
	COleVariant kwi(i,VT_I4), kt,kf;
	if(!pTags->Seek("=",&kwi))
		return 0;
	while(!pTags->IsEOF()) {
		kwi=pTags->GetFieldValue("wid");
		if(kwi.lVal!=i)
			break;
		kt=pTags->GetFieldValue("pos");
		kf=pTags->GetFieldValue("pfreq");
		p=new CTagFreq((LPCSTR) (kt.bstrVal), kf.lVal);
		a.Add(p);
		pTags->MoveNext();
	}
	return a.GetSize();
}

long CMyDictionary::Insert(CString w, long freq)
{//向词库中的words表加入一个词在语料库中的出现次数信息,freq的缺省值为1
	if(w.GetLength()>MaxWordLength || w=="") // w太长或为空
		return -1;

	COleVariant kw(w,VT_BSTRT), kf;
	pWords->SetCurrentIndex("word");
	if(pWords->Seek("=",&kw)) { // 如果这个词在词库中已经存在
		kf=pWords->GetFieldValue("wfreq");
		kf.lVal+=freq;
		pWords->Edit();
		pWords->SetFieldValue("wfreq",kf);
		pWords->Update();
		kf=pWords->GetFieldValue("wid");
	}
	else {// 如果这个词在词库中还不存在
		long recn=pWords->GetRecordCount(); // 查现有记录个数
		pWords->AddNew(); // 增加一条空白记录
		pWords->SetFieldValue("word",kw); // 设置word字段的值为当前词语
		kf=freq; // 对变量kf进行赋值
		pWords->SetFieldValue("wfreq",kf); // 设置freq字段的值
		kf.lVal=recn+1; // 在当前表中最后一条记录后添加一条新记录
		pWords->SetFieldValue("wid",kf); // 设置 wid字段的值
		pWords->Update(); // 更新数据库中的数据
	}
	return kf.lVal; // 返回该词语的 wid 信息(词语代号)
}

long CMyDictionary :: Insert(CString w, CString t, long freq)
{// 向词库中words表和poss表分别插入一个词以某种词性出现的次数,freq的缺省值为1
	if(w.GetLength()>MaxWordLength || w=="" || t.GetLength()>4 || t=="")
		return -1;

	long i=Insert(w); // 先更新词表中的词频信息,将该词的出现次数加1

	COleVariant kt(t,VT_BSTRT), kwi(i,VT_I4), kf;
	pTags->SetCurrentIndex("widTag");
	if(pTags->Seek("=",&kwi,&kt)) {
		kf=pTags->GetFieldValue("pfreq"); // 获取当前记录的pfreq值
		kf.lVal+=freq;
		pTags->Edit();
		pTags->SetFieldValue("pfreq",kf); // 设置poss表中pfreq中的值
		pTags->Update();
		kf=pTags->GetFieldValue("pid"); // 获取当前记录的pid值
	}
	else {
		long recn=pTags->GetRecordCount();
		pTags->AddNew();
		pTags->SetFieldValue("pos",kt); // 设置poss表中pos字段的值
		kf=freq;
		pTags->SetFieldValue("pfreq",kf); // 设置poss表中pfreq字段的值
		pTags->SetFieldValue("wid",kwi); // 设置poss表中wid字段的值
		kf.lVal=recn+1; // 在当前表中最后一条记录后添加一条新记录
		pTags->SetFieldValue("pid",kf); // 设置poss表中pid字段的值
		pTags->Update();
	}
	return kf.lVal;// 返回词语的词性标记序号值pid(词性标记代号)
}

///////////////////////////////////////////////////////////

CString CMyDictionary::GetTagOfWord(CString w)
{ //获取一个词语的词性标记
	CString tag="";
	long i;

	i=GetWordID(w);
	if(i==-1)
		tag="n"; // 所有未登录词的词性暂且假定为n
	pTags->SetCurrentIndex("wid");
	COleVariant kwi(i,VT_I4),kt;
	if(!pTags->Seek("=",&kwi))
		return tag;
//	else { // 取该词在词库中第一个词性标记
//		kt=pTags->GetFieldValue("pos");
//		tag=kt.bstrVal;
//	}
	
	while(!pTags->IsEOF()) {// 取该词所有词性标记,切词后,将一个词所有的词性标记
							// 加到分词符/后面
		kwi=pTags->GetFieldValue("wid");
		if(kwi.lVal!=i)
			break; // 如果当前词只有一个词性,并且标记为g,也会输出这个结果
		kt=pTags->GetFieldValue("pos");
		tag=kt.bstrVal; // 这条语句是为了只输出一个词性标记结果而添加的
//		if(tag!="") { // 被注释的语句是用来输出所有的词性标记
		if(tag!="g") { // 这里是只输出一个词性标记,并且该标记不是语素
//			tag=tag+"-"+kt.bstrVal;
			return tag;
		}
		else
//			tag=tag+kt.bstrVal;
		pTags->MoveNext();
	}

	return tag;
}

⌨️ 快捷键说明

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