ICTCLAS分詞系統研究(六)--得到初分結果
阿新 • • 發佈:2019-02-03
仍然以“他說的確實在理”為例,經過NshortPath的處理後,我們可以得到N條最短二叉分詞路徑,如下:
初次生成的分詞圖表:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
0 | 始##始 | |||||||
1 | 他 | |||||||
2 | 說 | |||||||
3 | 的 |
的確 | ||||||
4 | 確 | 確實 | ||||||
5 | 實 | 實在 |
||||||
6 | 在 | 在理 | ||||||
7 | 理 | |||||||
8 | 末##末 |
初次生成的二叉分詞圖表:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
1 | 他@說 | ||||||||||
2 | 說@的 | 說@的確 | |||||||||
3 | 的@確 | 的@確實 | |||||||||
4 | 的確@實 | 的確@實在 | |||||||||
5 | 確@實 | 確@實在 | |||||||||
6 | 確實@在 | 確實@在理 | |||||||||
7 | 實@在 | 實@在理 | |||||||||
8 | 實在@理 | ||||||||||
9 | 在@理 |
初次生成的二叉分詞路徑:
序號 | 二叉分詞路徑 |
0 | 0 1 2 3 6 9 11 12 |
1 | 0 1 2 4 7 9 11 12 |
2 | 0 1 2 3 5 7 9 11 12 |
0 1 2 3 6 9 11 12 指的是針對上圖二叉分詞圖表,得出的分詞路徑的列下標,其實圖表中的列對應的是@後面的詞,行對應的是@前面的詞在分詞圖表中的位置。得到了二叉分詞路徑,其實我們就可以得到真正的分詞路徑,只需要根據分詞圖表和二叉分詞圖表之間的對應關係進行一個簡單的轉換即可。
原始碼中是通過這一段程式碼來實現的:
while(i<m_nSegmentCount){
//把二叉分詞路徑轉成分詞路徑
BiPath2UniPath(nSegRoute[i]);
//根據分詞路徑生成分詞結果
GenerateWord(nSegRoute,i);
i++;
}
初次生成的分詞結果:
序號 | 分詞結果 |
0 | 他/ 說/ 的/ 確實/ 在/ 理/ |
1 | 他/ 說/ 的確/d 實/ 在/ 理/ |
2 | 他/ 說/ 的/ 確/ 實/ 在/ 理/ |
需要注意的是,在generateWord()函式裡對一些特殊情況做一些處理,然後再生成分詞結果。主要是對涉及到數字、時間、日期的結果進行合併、拆分,
//Generate Word according the segmentation routebool CSegment::GenerateWord(int**nSegRoute, int nIndex)
{
unsigned int i=0,k=0;
int j,nStartVertex,nEndVertex,nPOS;
char sAtom[WORD_MAXLENGTH],sNumCandidate[100],sCurWord[100];
ELEMENT_TYPE fValue;
while(nSegRoute[nIndex][i]!=-1&&nSegRoute[nIndex][i+1]!=-1&&nSegRoute[nIndex][i]<nSegRoute[nIndex][i+1])
{
nStartVertex=nSegRoute[nIndex][i];
j=nStartVertex;//Set the start vertex
nEndVertex=nSegRoute[nIndex][i+1];//Set the end vertex
nPOS=0;
m_graphSeg.m_segGraph.GetElement(nStartVertex,nEndVertex,&fValue,&nPOS);
sAtom[0]=0;
while(j<nEndVertex)
{//Generate the word according the segmentation route
strcat(sAtom,m_graphSeg.m_sAtom[j]);
j++;
}
m_pWordSeg[nIndex][k].sWord[0]=0;//Init the result ending
strcpy(sNumCandidate,sAtom);
//找出連續的數字串
while(sAtom[0]!=0&&(IsAllNum((unsigned char*)sNumCandidate)||IsAllChineseNum(sNumCandidate)))
{//Merge all seperate continue num into one number
//sAtom[0]!=0: add in 2002-5-9
strcpy(m_pWordSeg[nIndex][k].sWord,sNumCandidate);
//Save them in the result segmentation
i++;//Skip to next atom now
sAtom[0]=0;
while(j<nSegRoute[nIndex][i+1])
{//Generate the word according the segmentation route
strcat(sAtom,m_graphSeg.m_sAtom[j]);
j++;
}
strcat(sNumCandidate,sAtom);
}
unsigned int nLen=strlen(m_pWordSeg[nIndex][k].sWord);
if(nLen==4&&CC_Find("第上成±—+∶·./",m_pWordSeg[nIndex][k].sWord)||nLen==1&&strchr("+-./",m_pWordSeg[nIndex][k].sWord[0]))
{//Only one word
strcpy(sCurWord,m_pWordSeg[nIndex][k].sWord);//Record current word
i--;
}
elseif(m_pWordSeg[nIndex][k].sWord[0]==0)//Have never entering the while loop
{
strcpy(m_pWordSeg[nIndex][k].sWord,sAtom);
//Save them in the result segmentation
strcpy(sCurWord,sAtom);//Record current word
}
else
{//It is a num
if(strcmp("--",m_pWordSeg[nIndex][k].sWord)==0||strcmp("—",m_pWordSeg[nIndex][k].sWord)==0||m_pWordSeg[nIndex][k].sWord[0]=='-'&&m_pWordSeg[nIndex][k].sWord[1]==0)//The delimiter "--"
{
nPOS=30464;//'w'*256;Set the POS with 'w'
i--;//Not num, back to previous word
}
else
{//Adding time suffix
char sInitChar[3];
unsigned int nCharIndex=0;//Get first char
sInitChar[nCharIndex]=m_pWordSeg[nIndex][k].sWord[nCharIndex];
if(sInitChar[nCharIndex]<0)
{
nCharIndex+=1;
sInitChar[nCharIndex]=m_pWordSeg[nIndex][k].sWord[nCharIndex];
}
nCharIndex+=1;
sInitChar[nCharIndex]='