CN102063424A - 一种中文分词方法 - Google Patents

一种中文分词方法 Download PDF

Info

Publication number
CN102063424A
CN102063424A CN2010106051808A CN201010605180A CN102063424A CN 102063424 A CN102063424 A CN 102063424A CN 2010106051808 A CN2010106051808 A CN 2010106051808A CN 201010605180 A CN201010605180 A CN 201010605180A CN 102063424 A CN102063424 A CN 102063424A
Authority
CN
China
Prior art keywords
word
speech
sentence
chinese
character
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
CN2010106051808A
Other languages
English (en)
Inventor
赵孟德
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Shanghai Dianji University
Original Assignee
Shanghai Dianji University
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Shanghai Dianji University filed Critical Shanghai Dianji University
Priority to CN2010106051808A priority Critical patent/CN102063424A/zh
Publication of CN102063424A publication Critical patent/CN102063424A/zh
Pending legal-status Critical Current

Links

Images

Landscapes

  • Machine Translation (AREA)

Abstract

本发明提供一种中文分词方法,其所采用的最大匹配算法包含如下步骤:a1.从句子第1个字开始截取一个长度为i的字串,令它同词表中的词条依次匹配;a2.判断词表中是否能找到一个词条同当前字串匹配,如果是,则转入步骤a3,否则,转入步骤a5;a3.从句子第2个字开始截取一个长度为i的字串,令它同词表中的词条依次匹配,并进行步骤a4;a4.重复步骤a2和a3;a5.把这个字串作为一个词从句子中切分出去,把原句中位于这个字串左右两边的部分视为两个新的句子;a6.重复上述步骤。本发明能成功处理正向最大匹配算法(MM)和反向最大匹配(RMM)算法不能正确切分的句子,正确性和有效性比较高,可以高效地进行分词。

Description

一种中文分词方法
技术领域
本发明涉及一种信息处理领域中的中文分词技术,具体地说,是涉及一种中文分词方法。
背景技术
中文分词技术属于自然语言处理技术范畴,对于一句话,人可以通过自己的知识来明白哪些是词,哪些不是词,但如何让计算机也能理解?其处理过程就是分词算法。
现有的分词算法可分为三大类:基于理解的分词方法、基于统计的分词方法和基于字符串匹配的分词方法。
基于理解的分词方法,是通过让计算机模拟人对句子的理解,达到识别词的效果。其基本思想就是在分词的同时进行句法、语义分析,利用句法信息和语义信息来处理歧义现象。它通常包括三个部分:分词子系统、句法语义子系统、总控部分。在总控部分的协调下,分词子系统可以获得有关词、句子等的句法和语义信息来对分词歧义进行判断,即它模拟了人对句子的理解过程。这种分词方法需要使用大量的语言知识和信息。由于汉语语言知识的笼统、复杂性,难以将各种语言信息组织成机器可直接读取的形式,因此目前基于理解的分词系统还处在试验阶段。
基于统计的分词方法的原理是,从形式上看,词是稳定的字的组合,因此在上下文中,相邻的字同时出现的次数越多,就越有可能构成一个词。因此字与字相邻共现的频率或概率能够较好的反映成词的可信度。可以对语料中相邻共现的各个字的组合的频度进行统计,计算它们的互现信息。定义两个字的互现信息,计算两个汉字X、Y的相邻共现概率。互现信息体现了汉字之间结合关系的紧密程度。当紧密程度高于某一个阈值时,便可认为此字组可能构成了一个词。这种方法只需对语料中的字组频度进行统计,不需要切分词典,因而又叫做无词典分词法或统计取词方法。但这种方法也有一定的局限性,会经常抽出一些共现频度高、但并不是词的常用字组,例如“这一”、“之一”、“有的”、“我的”、“许多的”等,并且对常用词的识别精度差,时空开销大。实际应用的统计分词系统都要使用一部基本的分词词典(常用词词典)进行串匹配分词,同时使用统计方法识别一些新的词,即将串频统计和串匹配结合起来,既发挥匹配分词切分速度快、效率高的特点,又利用了无词典分词结合上下文识别生词、自动消除歧义的优点。
基于字符串匹配的分词方法,又叫做机械分词方法,它是按照一定的策略将待分析的汉字串与一个“充分大的”机器词典中的词条进行配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。按照扫描方向的不同,串匹配分词方法可以分为正向匹配和逆向匹配;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配;按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与标注相结合的一体化方法。常用的几种机械分词方法有:(1)正向最大匹配法(由左到右的方向);(2)逆向最大匹配法(由右到左的方向);(3)最少切分(使每一句中切出的词数最小)。还可以将这三种机械分词方法相互组合,例如,可以将正向最大匹配方法和逆向最大匹配方法结合起来构成双向匹配法。由于汉语单字成词的特点,正向最小匹配和逆向最小匹配一般很少使用。一般说来,逆向匹配的切分精度略高于正向匹配,遇到的歧义现象也较少。统计结果表明,单纯使用正向最大匹配的错误率为1/169,单纯使用逆向最大匹配的错误率为1/245。但这种精度还远远不能满足实际的需要。实际使用的分词系统,都是把机械分词作为一种初分手段,还需通过利用各种其它的语言信息来进一步提高切分的准确率。一种提高方法是改进扫描方式,称为特征扫描或标志切分,优先在待分析字符串中识别和切分出一些带有明显特征的词,以这些词作为断点,可将原字符串分为较小的串再来进机械分词,从而减少匹配的错误率。另一种提高方法是将分词和词类标注结合起来,利用丰富的词类信息对分词决策提供帮助,并且在标注过程中又反过来对分词结果进行检验、调整,从而极大地提高切分的准确率。
上述基于字符串匹配的分词方法,也就是机械分词方法中,不管是正向最大匹配法、逆向最大匹配法还是最少切分,这些最大匹配法的目的是试图在每分一个词时都尽量使其与词典中的词匹配长度最长。最大匹配法的优点是原理简单,易于实现,缺点是最大匹配长度不易确定,若太大则时间复杂度上升,太小则有些超过该长度的词无法匹配,降低了分词的准确率。最大匹配法的评价原则是“长词优先”。然而现有的最大匹配法不论顺向还是逆向,增字或减字,都是在局部范围进行最大匹配,即每次最大匹配的范围都是最先i 个或最后i 个字符,这样并没有充分体现“长词优先”的原则。
发明内容
本发明的目的在于克服现有技术的不足,提供一种能充分体现“长词优先”的原则,成功处理正向最大匹配算法(MM)和反向最大匹配(RMM)算法不能正确切分的句子的中文分词方法。
为达到上述目的,本发明采用如下技术方案:
一种中文分词方法,包含以下步骤: a. 分词,对汉字利用最大匹配算法;b. 将词标注词性; c. 进行命名识别;d. 重新分词,对汉字利用最大匹配算法;e. 将词标注准词性;所述步骤a中,对汉字利用最大匹配算法的过程包含如下步骤:
a1. 从句子第1 个字开始截取一个长度为i 的字串,令它同词表中的词条依次匹配;
a2. 判断词表中是否能找到一个词条同当前字串匹配,如果是,则转入步骤a3,否则,转入步骤a5;
a3.从句子第2 个字开始截取一个长度为i的字串,令它同词表中的词条依次匹配,并进行步骤a4;
a4. 重复步骤a2和a3;
a5. 把这个字串作为一个词从句子中切分出去,把原句中位于这个字串左右两边的部分视为两个新的句子;
a6. 重复上述步骤。
所述步骤a中的分词是将句子划分为单个的字符,其中汉字为单个的字,数值为连续的数字,英文为连续的英文字符,其它的标点符号为单独的一个字符。
对汉字利用最大匹配算法,寻找出所以的可能性的词的组合后,构建十字链表,利用平滑系数来确定最后的划词。
所述步骤b中,将划分的词标准词性,是利用词库中匹配的词标注词性。
本发明所采用的技术方案的优点是:
通过使现有的中文分词方法利用本发明的最大匹配算法,能更好地处理占总词数的比例较大的低音节词,从而成功处理正向最大匹配算法(MM)和反向最大匹配(RMM)算法不能正确切分的句子。另外,利用本发明的最大匹配算法与现有的信息量统计方法结合,可以很好的识别并消除交集型歧义。
下面结合附图对本发明的实施和优点作进一步解释。
附图说明
附图1是本发明的中文分词方法的流程示意图。
附图2是本发明的最大匹配算法的流程示意图。
具体实施方式
参见图1。中文分词方法包含以下步骤: 步骤Sa. 分词,对汉字利用最大匹配算法;步骤Sb. 将词标注词性; 步骤Sc. 进行命名识别;步骤Sd. 重新分词,对汉字利用最大匹配算法;步骤Se. 将词标注准词性。
参见图2。本申请是对上述步骤Sa中的最大匹配算法作了改进。如图所示,对汉字利用最大匹配算法的过程包含如下步骤:
步骤Sa1. 从句子第1 个字开始截取一个长度为i 的字串,令它同词表中的词条依次匹配。 假设词表中最长的词由i 个字组成,句子长度为N,采取归左原则进行切分。先从句子第1 个字开始截取一个长度为i 的字串(即句子的开头i 个字),令它同词表中的词条依次匹配;
步骤Sa2. 判断词表中是否能找到一个词条同当前字串匹配,如果是,则转入步骤Sa3,否则,转入步骤Sa5。 如果在词表中找不到一个词条能同当前字串匹配,就从句子第2 个字开始截取一个长度为i 的字串重复以上过程。如果还找不到,则依次从第3,4,……N-i 个字开始截取长度为i 的字串进行匹配。
步骤Sa3.从句子第2 个字开始截取一个长度为i的字串,令它同词表中的词条依次匹配,并进行步骤Sa4;如果所有的匹配都不成功,说明句子中没有长度为i 的词,则开始寻找长度i-1 的词。
步骤Sa4. 重复步骤Sa2和步骤Sa3;
步骤Sa5. 把这个字串作为一个词从句子中切分出去,把原句中位于这个字串左右两边的部分视为两个新的句子;如果在某一次匹配中查到词表中确有这样一个i 字词,匹配成功,并把这个字串作为一个词从句子中切分出去,把原句中位于这个字串左右两边的部分视为两个新的句子,递归调用这一过程。
步骤Sa6. 重复上述步骤。重复这个过程直到整个句子被完全切分。
改进后的算法在整个句子的范围内寻找最长词,充分体现了“长词优先”的原则,成功地处理了正向最大匹配算法(MM)和反向最大匹配(RMM)算法不能正确切分的句子。改进后的算法大致描述如下:
{for (j=MAXWORDLEN-1;j>=0;i--)//MAXWORDLEN 为词表的最大词长
{for(i=0;i<LEN;i++)// 常量LEN 为句子长度
{if(Match(S[i],j))// 判断是否有首字为S[i],长为j+1 的字段即搜索
{WordSegment(S[i]);// 把找到的首字为S[i],长为j+1 的字段切分出来
Segment(S[0],S[i-1]);// 对S[0]到S[i-1]的字串进行分词
if(i+j<LEN-1) // 对S[0]到S[i-1]的字串进行分词
break;}
} } }
参见图1和图2。输入的字符的处理流程如下:
一、分词:将句子划分为单个的字符,其中汉字为单个的字,数值为连续的数字,英文为连续的英文字符,其它的标点符号为单独的一个字符。
然后对汉字进行利用最大匹配算法,寻找出所以的可能性的词的组合,构建十字链表,利用平滑系数来确定最后的划词。
二、posTagging:将第一步划分的词标准词性,利用词库中匹配的词标注词性。这一步在分词阶段就通过数据字典来获取。
三、命名(NE)识别:人名识别,音译名识别,地名识别,利用定义的规则(中国人名,外国人名后缀,包括常用的地名-前后缀)来对名字实体识别。
四、重新分词:经过命名识别得出新的划词结果。这一步在NE识别是就同过字典获取后重新计算。
五、重新posTagging: 对第四部中的结果重新标注词性。
分词部分大概的思路:先进行原子切分,然后在此基础上进行N-最短路径粗切分,找出前N个最符合的切分结果,生成二元分词表,然后生成分词结果,接着进行词性标注并完成主要分词步骤。
原子切分按照上面所提到的汉字为单个的子,数值为连续的数字,英文为连续的英文字符,其它的标点符号为单独的一个字符的思路来实现的。代码如下:   
if(strncmp(sSentence,SENTENCE_BEGIN,strlen(SENTENCE_BEGIN))==0)
   {
       strcpy(m_sAtom[j],SENTENCE_BEGIN);//Set the first word as sentence begining
       m_nAtomLength[j]=strlen(SENTENCE_BEGIN);
       m_nAtomPOS[j]=CT_SENTENCE_BEGIN;//init
       i+=m_nAtomLength[j];
       j+=1;
       m_sAtom[j][0]=0;//Set the first word as null
       m_nAtomLength[j]=0;
   }
   while(i<strlen(sSentence))
   {
       if(strncmp(sSentence+i,SENTENCE_END,strlen(SENTENCE_END))==0)
       {
           strcpy(m_sAtom[j],SENTENCE_END);//Set the first word as null
           m_nAtomLength[j]=strlen(SENTENCE_END);
           m_nAtomPOS[j]=CT_SENTENCE_END;//init
           i+=m_nAtomLength[j];
           j+=1;
           m_sAtom[j][0]=0;//Set the first word as null
           m_nAtomLength[j]=0;
           continue;
       }
       sChar[0]=*(sSentence+i);//Get the char with first byte
       sChar[1]=0;//
       i+=1;
       if(sChar[0]<0)//Two byte char
       {
           sChar[1]=*(sSentence+i);//Get the char with second byte
           i+=1;//i increased by 1
       }
       strcat(m_sAtom[j],sChar);
       nCurType=charType((unsigned char *)sChar);
       if(sChar[0]=='.'&&(charType((unsigned char *)sSentence+i)==CT_NUM||(*(sSentence+i)>='0'&&*(sSentence+i)<='9')))
           nCurType=CT_NUM;//Digit after . indicate . as a point in the numeric
       m_nAtomPOS[j]=nCurType;
       //Record its property, just convience for continuous processing
if(nCurType==CT_CHINESE||nCurType==CT_INDEX||nCurType==CT_DELIMITER||nCurType==CT_OTHER)
       {//Chinese char, index number,delimiter and other is treated as atom
           m_nAtomLength[j]=strlen(m_sAtom[j]);//Save its length
           j+=1;//Skip to next atom
           m_sAtom[j][0]=0;//init
       }
       else 
       {nNextType=255;
           if(i<strlen(sSentence))
               nNextType=charType((unsigned char *)(sSentence+i));
           if(nNextType!=nCurType||i==strlen(sSentence))
           //Reaching end or next char type is different from current char
           {
               m_nAtomLength[j]=strlen(m_sAtom[j]);//Save its length   
               j+=1;
               m_sAtom[j][0]=0;//init
           }
       }
   }
2.N-最短路径粗切分
设置稀疏矩阵结构的值是一个重要的操作,主要是通过行和列找到要操作的节点,在此节点前插入新节点。其代码如下:
    if(nRow>m_nRow)//Set the array row
       m_nRow=nRow;
   if(nCol>m_nCol)//Set the array col
       m_nCol=nCol;
   if(m_bRowFirst)
   { while(pCur!=NULL&&(pCur->row<nRow||(pCur->row==nRow&&pCur->col<nCol)))
       {
           pPre=pCur;
           pCur=pCur->next;
       }
   }
   else
   {
   while(pCur!=NULL&&(pCur->col<nCol||(pCur->col==nCol&&pCur->row<nRow)))
       {
           pPre=pCur;
           pCur=pCur->next;
       }
   }
   if(pCur!=NULL&&pCur->row==nRow&&pCur->col==nCol)//Find the same position
   {
       pCur->value=fValue;//Set the value
       pCur->nPOS=nPOS;//Set the possible POS
   }
   else
   {
       pAdd=(PARRAY_CHAIN)malloc(sizeof(ARRAY_CHAIN));//malloc a new node
       pAdd->col=nCol;//get the value
       pAdd->row=nRow;
       pAdd->value=fValue;
       pAdd->nPOS=nPOS;
       if(sWord)//sWord is not empty
       {
           pAdd->nWordLen=strlen(sWord);
           pAdd->sWord=new char[pAdd->nWordLen+1];
           strcpy(pAdd->sWord,sWord);
       }
       else//sWord is Empty
       {
           pAdd->nWordLen=0;
           pAdd->sWord=NULL;
       }
       pAdd->next=pCur;
       if(pPre==NULL)//link pAdd after the pPre
           m_pHead=pAdd;
       else
           pPre->next=pAdd;
   }
   return 0;
}
在对已经切分的原子进行最大匹配时,主要通过查找字典获取最大长度匹配的词的方法,即图2所示的方法,GetMaxMatch()函数即为上述第4步中改进的长词优先的最大匹配方法,辅以该最大匹配规则限制,来取得最合后的原子。核心代码如下:
   while(i<m_nAtomCount)//All the word
   {
      strcpy(sWord,m_sAtom[i]);//Get the current atom
      j=i+1;
      if(strcmp(sWord,"月")==0&&strcmp(m_sAtom[i+1],"份")==0)//Don't split 月份
          j+=1;
      while(j<=m_nAtomCount&&dictCore.GetMaxMatch(sWord,sWordMatch,&nHandleTemp))
      {//Add a condition to control the end of string
       //retrieve the dictionary with the word
          if(strcmp(sWordMatch,sWord)==0)//find the current word
          {
              nTotalFreq=0;
              dictCore.GetHandle(sWord,&nMatchCount,nMatchHandle,nMatchFreq);
              for(k=0;k<nMatchCount;k++)//Add the frequency
              {
               nTotalFreq+=nMatchFreq[k];
              }
              //Adding a rule to exclude some words to be formed.
              if(strlen(sWord)==4&&i>=1&&(IsAllNum((unsigned char *)m_sAtom[i-1])||IsAllChineseNum(m_sAtom[i-1]))&&(strncmp(sWord,"年",2)==0||strncmp(sWord,"月",2)==0))
              {
                 if(CC_Find("末内中底前间初",sWord+2))
                     break;
              }
              if(nMatchCount==1)//The possible word has only one POS, store it
              {
               if(!bOriginalFreq)//Not original frequency
                   m_segGraph.SetElement(i,j,-log((double)nTotalFreq+1)+log(MAX_FREQUENCE),nMatchHandle[0]);
               else
                   m_segGraph.SetElement(i,j,nTotalFreq,nMatchHandle[0],sWord);
              }
              else 
              {
                   if(!bOriginalFreq)//Not original frequency
                       m_segGraph.SetElement(i,j,-log((double)nTotalFreq+1)+log(MAX_FREQUENCE),0);
                   else
                       m_segGraph.SetElement(i,j,nTotalFreq,0,sWord);
              }
          }
          strcat(sWord,m_sAtom[j++]);
      }
      i+=1;//Start from i++;
   }
经过出来后,结果为一个矩阵型的稀疏矩阵,即系统中的CDynamicArray结构实例了。其中:
struct tagArrayChain{
   unsigned int col,row;//row and column
        ELEMENT_TYPE value;//The value of the array
   int nPOS;   //Word pos, nPos=0 if has many pos, else nPos=firCh*256+secCh;
   int nWordLen;
   char *sWord; //The possible POS of the word related to the segmentation graph
   struct tagArrayChain *next;
};
接下来,要对此时系统中CDynamicArray结构的实例进行平滑处理,取最大的前N个词。平滑处理过程:遍历矩阵实例,对如其中每个节点,取出其值。
然后在找到节点行号等于当前节点列值的节点,从找到的节点开始遍历矩阵实例,将符合条件(行号等于列值的节点的词通过@链接起来)。核心代码如下:
   while(pCur!=NULL)//
   {
       if(pCur->nPOS>=0)//It's not an unknown words
           dCurFreqency=pCur->value;
       else//Unknown words
           dCurFreqency=DictCore.GetFrequency(pCur->sWord,2);
       aWord.GetElement(pCur->col,-1,pCur,&pNextWords);//Get next words which begin with pCur->col
       while(pNextWords&&pNextWords->row==pCur->col)//Next words
       {   
           //Current words frequency
           strcpy(sTwoWords,pCur->sWord);
           strcat(sTwoWords,WORD_SEGMENTER);
           strcat(sTwoWords,pNextWords->sWord);
           nTwoWordsFreq=DictBinary.GetFrequency(sTwoWords,3);
           //Two linked Words frequency
           dTemp=(double)1/MAX_FREQUENCE;
           //Smoothing
     dValue=-log(dSmoothingPara*(1+dCurFreqency)/(MAX_FREQUENCE+80000)+(1-dSmoothingPara)*((1-dTemp)*nTwoWordsFreq/(1+dCurFreqency)+dTemp));
           //-log{a*P(Ci-1)+(1-a)P(Ci|Ci-1)} Note 0<a<1
           if(pCur->nPOS<0)//Unknown words: P(Wi|Ci);while known words:1
                dValue+=pCur->value;
           //Get the position index of current word in the position map table
           nCurWordIndex=BinarySearch(pCur->row*MAX_SENTENCE_LEN+pCur->col,m_npWordPosMapTable,m_nWordCount);
           nNextWordIndex=BinarySearch(pNextWords->row*MAX_SENTENCE_LEN+pNextWords->col,m_npWordPosMapTable,m_nWordCount);
           aBinaryWordNet.SetElement(nCurWordIndex,nNextWordIndex,dValue,pCur->nPOS);
           pNextWords=pNextWords->next;//Get next word
       }
       pCur=pCur->next;
   }
得到链接后的矩阵,再进行路径计算,得到N个词。所谓N最短路径其实就是最短路径和最大路径的折中,保留前N个最优路径。这样做的目的就是对这两种方法一个折衷做法。
Queue的数据结构如下所示:
---tagQueueElem--
|nParent;//the weight
|nIndex;//number of index in the parent node
|ELEMENT_TYPE eWeight;//the weight of last path
|tagQueueElem *next;
-parent----element------------------------------------------------
|Queue1 QueueElement1 QueueElement2 ..... QueueElement_nValueKind
|
|Queue2 QueueElement1 QueueElement2 ..... QueueElement_nValueKind
|
|Queue3 QueueElement1 QueueElement2 ..... QueueElement_nValueKind
|
|Queue m_nVertex QueueElement1 QueueElement2 ..... QueueElement_nValueKind
对于ShorPath的构函数,实现功能:
遍历每个Queue(m_nVertex个),对于每个queue横向遍历,将当前节点有效权值+当前行首的权值的值之和,以权衡升序压入堆栈。
int CNShortPath::ShortPath()
{
   unsigned int nCurNode=1,nPreNode,i,nIndex;
   ELEMENT_TYPE eWeight;
   PARRAY_CHAIN pEdgeList;
    for(;nCurNode<m_nVertex;nCurNode++)
   {
       CQueue queWork;
       eWeight=m_apCost->GetElement(-1,nCurNode,0,&pEdgeList);//Get all the edges
       while(pEdgeList!=0 && pEdgeList->col==nCurNode)
       {
           nPreNode=pEdgeList->row;
           eWeight=pEdgeList->value;//Get the value of edges
           for(i=0;i<m_nValueKind;i++)
           {
               if(nPreNode>0)//Push the weight and the pre node infomation
               {
                   if(m_pWeight[nPreNode-1][i]==INFINITE_VALUE)
                       break;
                   queWork.Push(nPreNode,i,eWeight+m_pWeight[nPreNode-1][i]);
               }
               else
               {
                   queWork.Push(nPreNode,i,eWeight);
                   break;
               }
           }//end for
           pEdgeList=pEdgeList->next;
       }
       //Now get the result queue which sort as weight.
       //Set the current node information
       for(i=0;i<m_nValueKind;i++)
       {
           m_pWeight[nCurNode-1][i]=INFINITE_VALUE;
       }
       //memset((void *),(int),sizeof(ELEMENT_TYPE)*);
       //init the weight
       i=0;      
       while(i<m_nValueKind&&queWork.Pop(&nPreNode,&nIndex,&eWeight)!=-1)
       {//Set the current node weight and parent
           if(m_pWeight[nCurNode-1][i]==INFINITE_VALUE)
               m_pWeight[nCurNode-1][i]=eWeight;
           else if(m_pWeight[nCurNode-1][i]<eWeight)//Next queue
           {
               i++;//Go next queue and record next weight
               if(i==m_nValueKind)//Get the last position
                   break;
               m_pWeight[nCurNode-1][i]=eWeight;
           }
           m_pParent[nCurNode-1][i].Push(nPreNode,nIndex);
       }
   }//end for
   return 1;
]
输出时,只关注于结构最优的那个结果。从Parent中输出到Result中。
其输出部分核心代码为:
CQueue queResult;
   unsigned int nCurNode,nCurIndex,nParentNode,nParentIndex,nResultIndex=0;
   if(m_nResultCount>=MAX_SEGMENT_NUM)//Only need 10 result
       return ;
   nResult[m_nResultCount][nResultIndex]=-1;//Init the result 
   queResult.Push(nNode,nIndex);
    nCurNode=nNode;
   nCurIndex=nIndex;
    bool bFirstGet;
    while(!queResult.IsEmpty())
   {
       while(nCurNode>0)//
       {//Get its parent and store them in nParentNode,nParentIndex
           if(m_pParent[nCurNode-1][nCurIndex].Pop(&nParentNode,&nParentIndex,0,false,true)!=-1)
           {
               nCurNode=nParentNode;
               nCurIndex=nParentIndex;
           }
           if(nCurNode>0)
                queResult.Push(nCurNode,nCurIndex);
       }
       if(nCurNode==0)
       { //Get a path and output           nResult[m_nResultCount][nResultIndex++]=nCurNode;
//Get the first node
           bFirstGet=true;
           nParentNode=nCurNode;
           while(queResult.Pop(&nCurNode,&nCurIndex,0,false,bFirstGet)!=-1)
           {
               nResult[m_nResultCount][nResultIndex++]=nCurNode;
               bFirstGet=false;
               nParentNode=nCurNode;
           }
           nResult[m_nResultCount][nResultIndex]=-1;//Set the end
           m_nResultCount+=1;//The number of result add by 1
           if(m_nResultCount>=MAX_SEGMENT_NUM)//Only need 10 result
               return ;
           nResultIndex=0;
           nResult[m_nResultCount][nResultIndex]=-1;//Init the result 
           if(bBest)//Return the best result, ignore others
               return ;
       }
       queResult.Pop(&nCurNode,&nCurIndex,0,false,true);//Read the top node
        while(queResult.IsEmpty()==false&&(m_pParent[nCurNode-1][nCurIndex].IsSingle()||m_pParent[nCurNode-1][nCurIndex].IsEmpty(true)))
       {
           queResult.Pop(&nCurNode,&nCurIndex,0);//Get rid of it
           queResult.Pop(&nCurNode,&nCurIndex,0,false,true);//Read the top node
       }
        if(queResult.IsEmpty()==false&&m_pParent[nCurNode-1][nCurIndex].IsEmpty(true)==false)
       {
m_pParent[nCurNode-1][nCurIndex].Pop(&nParentNode,&nParentIndex,0,false,false);
               nCurNode=nParentNode;
               nCurIndex=nParentIndex;
               if(nCurNode>0)
                   queResult.Push(nCurNode,nCurIndex);
       }
   }
本申请的技术构思是:基于最大匹配法的评价原则是“长词优先”,而现有的最大匹配法不论顺向还是逆向,增字或减字,都是在局部范围进行最大匹配,即每次最大匹配的范围都是最先i 个或最后i 个字符,这样并没有充分体现“长词优先”的原则。针对这种情况,本发明的发明人提出一种改进的最大匹配算法。鉴于低音节词占总词数的比例较大,提出一种基于优化最大匹配的中文分词算法,提高查询的效率和时间复杂度。考虑到信息量统计处理歧义问题,由于交集型歧义字段占歧义字段总数量的85%以上,因此本发明在利用现有信息量统计方法的基础上,改进最大匹配规则,处理交集型字段。
实验表明,本申请所提供的方法的正确性和有效性比较高,系统可以高效地进行分词,本发明优化的最大匹配方法可以很好的识别并消除交集型歧义。
本申请改进后的算法在整个句子的范围内寻找最长词,通过对改进后的最大匹配算法中文分词系统对语料的实际分析,能够充分体现“长词优先”的原则,使分词精度大大提高,成功处理正向最大匹配算法(MM)和反向最大匹配(RMM)算法不能正确切分的句子,避免MM 法和RMM 法的一部分错误切分。另外,现有的预处理方法可以不加修改地应用于包含本申请的最大匹配方法的所有的机械分词方法特别是全切分方法,也可以用于消除歧义。  
当然,以上仅是本发明的具体应用范例,对本发明的保护范围不构成任何限制。除上述实施例外,本发明还可以有其它实施方式。凡采用等同替换或等效变换形成的技术方案,均落在本发明所要求保护的范围之内。

Claims (4)

1. 一种中文分词方法,包含以下步骤: a. 分词,对汉字利用最大匹配算法;b. 将词标注词性; c. 进行命名识别;d. 重新分词,对汉字利用最大匹配算法;e. 将词标注准词性;其特征在于,所述步骤a中,对汉字利用最大匹配算法的过程包含如下步骤:
a1. 从句子第1 个字开始截取一个长度为i 的字串,令它同词表中的词条依次匹配;
a2. 判断词表中是否能找到一个词条同当前字串匹配,如果是,则转入步骤a3,否则,转入步骤a5;
a3.从句子第2 个字开始截取一个长度为i的字串,令它同词表中的词条依次匹配,并进行步骤a4;
a4. 重复步骤a2和a3;
a5. 把这个字串作为一个词从句子中切分出去,把原句中位于这个字串左右两边的部分视为两个新的句子;
a6. 重复上述步骤。
2.根据权利要求1所述的中文分词方法,其特征在于,所述步骤a中的分词是将句子划分为单个的字符,其中汉字为单个的字,数值为连续的数字,英文为连续的英文字符,其它的标点符号为单独的一个字符。
3.根据权利要求1所述的中文分词方法,其特征在于,对汉字利用最大匹配算法,寻找出所以的可能性的词的组合后,构建十字链表,利用平滑系数来确定最后的划词。
4.根据权利要求1所述的中文分词方法,其特征在于,所述步骤b中,将划分的词标准词性,是利用词库中匹配的词标注词性。
CN2010106051808A 2010-12-24 2010-12-24 一种中文分词方法 Pending CN102063424A (zh)

Priority Applications (1)

Application Number Priority Date Filing Date Title
CN2010106051808A CN102063424A (zh) 2010-12-24 2010-12-24 一种中文分词方法

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN2010106051808A CN102063424A (zh) 2010-12-24 2010-12-24 一种中文分词方法

Publications (1)

Publication Number Publication Date
CN102063424A true CN102063424A (zh) 2011-05-18

Family

ID=43998705

Family Applications (1)

Application Number Title Priority Date Filing Date
CN2010106051808A Pending CN102063424A (zh) 2010-12-24 2010-12-24 一种中文分词方法

Country Status (1)

Country Link
CN (1) CN102063424A (zh)

Cited By (15)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN102298618A (zh) * 2011-08-03 2011-12-28 百度在线网络技术(北京)有限公司 一种获取匹配度以执行相应操作的方法、装置及设备
CN102402502A (zh) * 2011-11-24 2012-04-04 北京趣拿信息技术有限公司 用于搜索引擎的分词处理方法和装置
CN103544167A (zh) * 2012-07-13 2014-01-29 江苏新瑞峰信息科技有限公司 一种基于中文检索的逆向分词方法及装置
CN103577391A (zh) * 2012-07-28 2014-02-12 江苏新瑞峰信息科技有限公司 一种基于中文检索的双向分词方法及装置
CN103646018A (zh) * 2013-12-20 2014-03-19 大连大学 一种基于hash散列表词典结构的中文分词方法
CN104252542A (zh) * 2014-09-29 2014-12-31 南京航空航天大学 一种基于词库的动态规划中文分词方法
CN104462105A (zh) * 2013-09-16 2015-03-25 腾讯科技(深圳)有限公司 中文分词方法、装置和服务器
CN105138514A (zh) * 2015-08-24 2015-12-09 昆明理工大学 一种基于词典的正向逐次加一字最大匹配中文分词方法
CN106653005A (zh) * 2016-11-23 2017-05-10 河池学院 一种机器人的语音处理方法
CN107622044A (zh) * 2016-07-13 2018-01-23 阿里巴巴集团控股有限公司 字符串的分词方法、装置及设备
CN108363729A (zh) * 2018-01-12 2018-08-03 中国平安人寿保险股份有限公司 一种字符串比较方法、装置、终端设备及存储介质
CN108491373A (zh) * 2018-02-01 2018-09-04 北京百度网讯科技有限公司 一种实体识别方法及系统
CN108664468A (zh) * 2018-05-02 2018-10-16 武汉烽火普天信息技术有限公司 一种基于词典和语义消歧的人名识别方法和装置
CN110009777A (zh) * 2019-03-22 2019-07-12 国网福建省电力有限公司福州供电公司 一种自动匹配工作票任务的开锁序列生成方法及系统
CN110399452A (zh) * 2019-07-23 2019-11-01 福建奇点时空数字科技有限公司 一种基于实例特征建模的命名实体列表生成方法

Cited By (21)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN102298618A (zh) * 2011-08-03 2011-12-28 百度在线网络技术(北京)有限公司 一种获取匹配度以执行相应操作的方法、装置及设备
CN102402502A (zh) * 2011-11-24 2012-04-04 北京趣拿信息技术有限公司 用于搜索引擎的分词处理方法和装置
CN103544167A (zh) * 2012-07-13 2014-01-29 江苏新瑞峰信息科技有限公司 一种基于中文检索的逆向分词方法及装置
CN103577391A (zh) * 2012-07-28 2014-02-12 江苏新瑞峰信息科技有限公司 一种基于中文检索的双向分词方法及装置
CN104462105B (zh) * 2013-09-16 2019-01-22 腾讯科技(深圳)有限公司 中文分词方法、装置和服务器
CN104462105A (zh) * 2013-09-16 2015-03-25 腾讯科技(深圳)有限公司 中文分词方法、装置和服务器
US11003700B2 (en) 2013-09-16 2021-05-11 Tencent Technology (Shenzhen) Company Limited Methods and systems for query segmentation in a search
CN103646018A (zh) * 2013-12-20 2014-03-19 大连大学 一种基于hash散列表词典结构的中文分词方法
CN103646018B (zh) * 2013-12-20 2016-06-29 大连大学 一种基于hash散列表词典结构的中文分词方法
CN104252542A (zh) * 2014-09-29 2014-12-31 南京航空航天大学 一种基于词库的动态规划中文分词方法
CN105138514B (zh) * 2015-08-24 2018-11-09 昆明理工大学 一种基于词典的正向逐次加一字最大匹配中文分词方法
CN105138514A (zh) * 2015-08-24 2015-12-09 昆明理工大学 一种基于词典的正向逐次加一字最大匹配中文分词方法
CN107622044A (zh) * 2016-07-13 2018-01-23 阿里巴巴集团控股有限公司 字符串的分词方法、装置及设备
CN106653005A (zh) * 2016-11-23 2017-05-10 河池学院 一种机器人的语音处理方法
CN108363729A (zh) * 2018-01-12 2018-08-03 中国平安人寿保险股份有限公司 一种字符串比较方法、装置、终端设备及存储介质
CN108491373A (zh) * 2018-02-01 2018-09-04 北京百度网讯科技有限公司 一种实体识别方法及系统
CN108491373B (zh) * 2018-02-01 2022-05-27 北京百度网讯科技有限公司 一种实体识别方法及系统
CN108664468A (zh) * 2018-05-02 2018-10-16 武汉烽火普天信息技术有限公司 一种基于词典和语义消歧的人名识别方法和装置
CN110009777A (zh) * 2019-03-22 2019-07-12 国网福建省电力有限公司福州供电公司 一种自动匹配工作票任务的开锁序列生成方法及系统
CN110009777B (zh) * 2019-03-22 2021-06-22 国网福建省电力有限公司福州供电公司 一种自动匹配工作票任务的开锁序列生成方法及系统
CN110399452A (zh) * 2019-07-23 2019-11-01 福建奇点时空数字科技有限公司 一种基于实例特征建模的命名实体列表生成方法

Similar Documents

Publication Publication Date Title
CN102063424A (zh) 一种中文分词方法
CN104391942B (zh) 基于语义图谱的短文本特征扩展方法
Jung Semantic vector learning for natural language understanding
CN104699763B (zh) 多特征融合的文本相似性度量系统
US20170213157A1 (en) Method and system to provide related data
CN111931506B (zh) 一种基于图信息增强的实体关系抽取方法
CN101079025B (zh) 一种文档相关度计算系统和方法
CN106599032B (zh) 一种结合稀疏编码和结构感知机的文本事件抽取方法
CN103646112B (zh) 利用了网络搜索的依存句法的领域自适应方法
CN109145260A (zh) 一种文本信息自动提取方法
CN103150381B (zh) 一种高精度汉语谓词识别方法
CN103399901A (zh) 一种关键词抽取方法
CN104008090A (zh) 一种基于概念向量模型的多主题提取方法
CN110175585B (zh) 一种简答题自动批改系统及方法
CN102622338A (zh) 一种短文本间语义距离的计算机辅助计算方法
CN103970730A (zh) 一种从单个中文文本中提取多主题词的方法
CN106528524A (zh) 一种基于MMseg算法与逐点互信息算法的分词方法
CN112417854A (zh) 中文文档抽取式摘要方法
CN112051986B (zh) 基于开源知识的代码搜索推荐装置及方法
CN105975475A (zh) 基于中文短语串的细粒度主题信息抽取方法
Mirroshandel et al. Active learning for dependency parsing using partially annotated sentences
CN114139533A (zh) 一种面向中文小说领域的文本内容审核方法
CN112926345A (zh) 基于数据增强训练的多特征融合神经机器翻译检错方法
CN104317882A (zh) 一种决策级中文分词融合方法
CN114997288A (zh) 一种设计资源关联方法

Legal Events

Date Code Title Description
C06 Publication
PB01 Publication
C10 Entry into substantive examination
SE01 Entry into force of request for substantive examination
C12 Rejection of a patent application after its publication
RJ01 Rejection of invention patent application after publication

Application publication date: 20110518