Dictionary.cpp
上传用户:yxl0916
上传日期:2007-05-25
资源大小:2245k
文件大小:33k
源码类别:

多国语言处理

开发平台:

Visual C++

  1. //////////////////////////////////////////////////////////////////////
  2. //ICTCLAS简介:计算所汉语词法分析系统ICTCLAS(Institute of Computing Technology, Chinese Lexical Analysis System),
  3. //             功能有:中文分词;词性标注;未登录词识别。
  4. //             分词正确率高达97.58%(973专家评测结果),
  5. //             未登录词识别召回率均高于90%,其中中国人名的识别召回率接近98%;
  6. //             处理速度为31.5Kbytes/s。
  7. //著作权:  Copyright?2002-2005中科院计算所 职务著作权人:张华平 刘群
  8. //遵循协议:自然语言处理开放资源许可证1.0
  9. //Email: zhanghp@software.ict.ac.cn
  10. //Homepage:www.nlp.org.cn;mtgroup.ict.ac.cn
  11. /****************************************************************************
  12.  *
  13.  * Copyright (c) 2000, 2001 
  14.  *     Machine Group
  15.  *     Software Research Lab.
  16.  *     Institute of Computing Tech.
  17.  *     Chinese Academy of Sciences
  18.  *     All rights reserved.
  19.  *
  20.  * This file is the confidential and proprietary property of 
  21.  * Institute of Computing Tech. and the posession or use of this file requires 
  22.  * a written license from the author.
  23.  * Filename: Dictionary.cpp
  24.  * Abstract:
  25.  *           implementation of the CDictionary class.
  26.  * Author:   Kevin Zhang 
  27.  *          (zhanghp@software.ict.ac.cn)
  28.  * Date:     2002-1-8
  29.  *
  30.  * Notes:
  31.  *                
  32.  ****************************************************************************/
  33. #include "stdafx.h"
  34. #include "Dictionary.h"
  35. #include "Utility.h"
  36. #include <string.h>
  37. #include <stdlib.h>
  38. #include <malloc.h>
  39. #include <stdio.h>
  40. //////////////////////////////////////////////////////////////////////
  41. // Construction/Destruction
  42. //////////////////////////////////////////////////////////////////////
  43. CDictionary::CDictionary()
  44. {
  45.   //initilization
  46.   memset(m_IndexTable,0,sizeof(m_IndexTable));
  47.   m_pModifyTable=NULL;
  48. }
  49. CDictionary::~CDictionary()
  50. {
  51. for(int i=0;i<CC_NUM;i++)
  52. {//delete the memory of word item array in the dictionary
  53. for(int j=0;j<m_IndexTable[i].nCount;j++)
  54. delete m_IndexTable[i].pWordItemHead[j].sWord;
  55. delete [] m_IndexTable[i].pWordItemHead;
  56. }
  57.     DelModified();
  58. }
  59. /*********************************************************************
  60.  *
  61.  *  Func Name  : Load
  62.  *
  63.  *  Description: Load the dictionary from the file .dct
  64.  *              
  65.  *
  66.  *  Parameters : sFilename: the file name
  67.  *
  68.  *  Returns    : success or fail
  69.  *  Author     : Kevin Zhang  
  70.  *  History    : 
  71.  *              1.create 2002-1-9
  72.  *********************************************************************/
  73. bool CDictionary::Load(char *sFilename,bool bReset)
  74. {
  75.    FILE *fp;
  76.    int i,j,nBuffer[3];
  77.    if((fp=fopen(sFilename,"rb"))==NULL)
  78.    return false;//fail while opening the file
  79.    
  80.    //Release the memory for new files
  81.    for( i=0;i<CC_NUM;i++)
  82. {//delete the memory of word item array in the dictionary
  83. for( j=0;j<m_IndexTable[i].nCount;j++)
  84. delete m_IndexTable[i].pWordItemHead[j].sWord;
  85. delete [] m_IndexTable[i].pWordItemHead;
  86. }
  87.     DelModified();
  88.    for(i=0;i<CC_NUM;i++)
  89.    {
  90.    fread(&(m_IndexTable[i].nCount),sizeof(int),1,fp);
  91.        if(m_IndexTable[i].nCount>0)
  92.      m_IndexTable[i].pWordItemHead=new WORD_ITEM[m_IndexTable[i].nCount];
  93.    else 
  94.    {
  95.    m_IndexTable[i].pWordItemHead=0;
  96.    continue;
  97.    }
  98.        j=0;
  99.    while(j<m_IndexTable[i].nCount)
  100.    {
  101.          fread(nBuffer,sizeof(int),3,fp);
  102.          m_IndexTable[i].pWordItemHead[j].sWord=new char[nBuffer[1]+1];
  103.     if(nBuffer[1])//String length is more than 0
  104.  {
  105.  fread(m_IndexTable[i].pWordItemHead[j].sWord,sizeof(char),nBuffer[1],fp);
  106.  }
  107.  m_IndexTable[i].pWordItemHead[j].sWord[nBuffer[1]]=0;
  108.         if(bReset)//Reset the frequency
  109.           m_IndexTable[i].pWordItemHead[j].nFrequency=0;
  110.  else
  111.               m_IndexTable[i].pWordItemHead[j].nFrequency=nBuffer[0];
  112.  m_IndexTable[i].pWordItemHead[j].nWordLen=nBuffer[1];
  113.  m_IndexTable[i].pWordItemHead[j].nHandle=nBuffer[2];
  114.    j+=1;//Get next item in the original table.
  115.    }
  116.    }
  117.    fclose(fp);
  118.    return true;
  119. }
  120. /*********************************************************************
  121.  *
  122.  *  Func Name  : Save
  123.  *
  124.  *  Description: Save the dictionary as the file .dct
  125.  *              
  126.  *
  127.  *  Parameters : sFilename: the file name
  128.  *
  129.  *  Returns    : success or fail
  130.  *  Author     : Kevin Zhang  
  131.  *  History    : 
  132.  *              1.create 2002-1-9
  133.  *********************************************************************/
  134. bool CDictionary::Save(char *sFilename)
  135. {
  136.    FILE *fp;
  137.    int i,j,nCount,nBuffer[3];
  138.    PWORD_CHAIN pCur;
  139.    if((fp=fopen(sFilename,"wb"))==NULL)
  140.    return false;//fail while opening the file
  141.    for(i=0;i<CC_NUM;i++)
  142.    {
  143.    pCur=NULL;
  144.    if(m_pModifyTable)
  145.    {//Modification made
  146.    nCount=m_IndexTable[i].nCount+m_pModifyTable[i].nCount-m_pModifyTable[i].nDelete;
  147.    fwrite(&nCount,sizeof(int),1,fp);
  148.    pCur=m_pModifyTable[i].pWordItemHead;
  149.    j=0;
  150.    while(pCur!=NULL&&j<m_IndexTable[i].nCount)
  151.    {//Output to the file after comparision
  152.    if(strcmp(pCur->data.sWord,m_IndexTable[i].pWordItemHead[j].sWord)<0||(strcmp(pCur->data.sWord,m_IndexTable[i].pWordItemHead[j].sWord)==0&&pCur->data.nHandle<m_IndexTable[i].pWordItemHead[j].nHandle))
  153.    {//Output the modified data to the file
  154.  nBuffer[0]=pCur->data.nFrequency;
  155.          nBuffer[1]=pCur->data.nWordLen;
  156.      nBuffer[2]=pCur->data.nHandle;
  157.                  fwrite(nBuffer,sizeof(int),3,fp);
  158.  if(nBuffer[1])//String length is more than 0
  159.           fwrite(pCur->data.sWord,sizeof(char),nBuffer[1],fp);
  160.                  pCur=pCur->next;//Get next item in the modify table.
  161.    }
  162.    else if(m_IndexTable[i].pWordItemHead[j].nFrequency==-1)
  163.    {//The item has been removed,so skip it
  164.    j+=1;
  165.    }
  166.    else if(strcmp(pCur->data.sWord,m_IndexTable[i].pWordItemHead[j].sWord)>0||(strcmp(pCur->data.sWord,m_IndexTable[i].pWordItemHead[j].sWord)==0&&pCur->data.nHandle>m_IndexTable[i].pWordItemHead[j].nHandle))
  167.    {//Output the index table data to the file
  168.  nBuffer[0]=m_IndexTable[i].pWordItemHead[j].nFrequency;
  169.  nBuffer[1]=m_IndexTable[i].pWordItemHead[j].nWordLen;
  170.  nBuffer[2]=m_IndexTable[i].pWordItemHead[j].nHandle;
  171.  fwrite(nBuffer,sizeof(int),3,fp);
  172.  if(nBuffer[1])//String length is more than 0
  173.    fwrite(m_IndexTable[i].pWordItemHead[j].sWord,sizeof(char),nBuffer[1],fp);
  174.  j+=1;//Get next item in the original table.
  175.    }
  176.    }
  177.    if(j<m_IndexTable[i].nCount)
  178.    {
  179.    while(j<m_IndexTable[i].nCount)
  180.    {
  181.    if(m_IndexTable[i].pWordItemHead[j].nFrequency!=-1)
  182.    {//Has been deleted
  183.  nBuffer[0]=m_IndexTable[i].pWordItemHead[j].nFrequency;
  184.  nBuffer[1]=m_IndexTable[i].pWordItemHead[j].nWordLen;
  185.  nBuffer[2]=m_IndexTable[i].pWordItemHead[j].nHandle;
  186.  fwrite(nBuffer,sizeof(int),3,fp);
  187.  if(nBuffer[1])//String length is more than 0
  188.    fwrite(m_IndexTable[i].pWordItemHead[j].sWord,sizeof(char),nBuffer[1],fp);
  189.    }
  190.    j+=1;//Get next item in the original table.
  191.    }
  192.    }
  193.    else////No Modification
  194.    while(pCur!=NULL)//Add the rest data to the file.
  195.    {
  196.  nBuffer[0]=pCur->data.nFrequency;
  197.          nBuffer[1]=pCur->data.nWordLen;
  198.      nBuffer[2]=pCur->data.nHandle;
  199.                  fwrite(nBuffer,sizeof(int),3,fp);
  200.  if(nBuffer[1])//String length is more than 0
  201.    fwrite(pCur->data.sWord,sizeof(char),nBuffer[1],fp);
  202.                  pCur=pCur->next;//Get next item in the modify table.
  203.    }
  204.    }
  205.    else
  206.    {
  207.    fwrite(&m_IndexTable[i].nCount,sizeof(int),1,fp);
  208.    //write to the file
  209.            j=0;  
  210.    while(j<m_IndexTable[i].nCount)
  211.    {
  212.  nBuffer[0]=m_IndexTable[i].pWordItemHead[j].nFrequency;
  213.      nBuffer[1]=m_IndexTable[i].pWordItemHead[j].nWordLen;
  214.  nBuffer[2]=m_IndexTable[i].pWordItemHead[j].nHandle;
  215.              fwrite(nBuffer,sizeof(int),3,fp);
  216.  if(nBuffer[1])//String length is more than 0
  217.    fwrite(m_IndexTable[i].pWordItemHead[j].sWord,sizeof(char),nBuffer[1],fp);
  218.    j+=1;//Get next item in the original table.
  219.    }
  220.    }
  221.    }
  222.    fclose(fp);
  223.    return true;
  224. }
  225. /*********************************************************************
  226.  *
  227.  *  Func Name  : AddItem
  228.  *
  229.  *  Description: Add a word item to the dictionary
  230.  *              
  231.  *
  232.  *  Parameters : sWord: the word
  233.  *               nHandle:the handle number
  234.  *               nFrequency: the frequency
  235.  *  Returns    : success or fail
  236.  *  Author     : Kevin Zhang  
  237.  *  History    : 
  238.  *              1.create 2002-1-9
  239.  *********************************************************************/
  240. bool CDictionary::AddItem(char *sWord, int nHandle,int nFrequency)
  241. {
  242.    char sWordAdd[WORD_MAXLENGTH-2];
  243.    int nPos,nFoundPos;
  244.    PWORD_CHAIN pRet,pTemp,pNext;
  245.    int i=0;
  246.    if(!PreProcessing(sWord, &nPos,sWordAdd,true))
  247.    return false;
  248.    if(FindInOriginalTable(nPos,sWordAdd,nHandle,&nFoundPos))
  249.    {//The word exists in the original table, so add the frequency
  250.     //Operation in the index table and its items 
  251.        if(m_IndexTable[nPos].pWordItemHead[nFoundPos].nFrequency==-1)
  252.    {//The word item has been removed
  253.       m_IndexTable[nPos].pWordItemHead[nFoundPos].nFrequency=nFrequency;
  254.         if(!m_pModifyTable)//Not prepare the buffer
  255.   {
  256.    m_pModifyTable=new MODIFY_TABLE[CC_NUM];
  257.    memset(m_pModifyTable,0,CC_NUM*sizeof(MODIFY_TABLE));
  258.   }
  259.   m_pModifyTable[nPos].nDelete-=1;
  260.    }
  261.    else
  262.   m_IndexTable[nPos].pWordItemHead[nFoundPos].nFrequency+=nFrequency;
  263.    return true;
  264.    }
  265.    //The items not exists in the index table.
  266.    //As following, we have to find the item whether exists in the modify data region
  267.    //If exists, change the frequency .or else add a item
  268.    if(!m_pModifyTable)//Not prepare the buffer
  269.    {
  270.    m_pModifyTable=new MODIFY_TABLE[CC_NUM];
  271.    memset(m_pModifyTable,0,CC_NUM*sizeof(MODIFY_TABLE));
  272.    }
  273.    if(FindInModifyTable(nPos,sWordAdd,nHandle,&pRet))
  274.    {
  275.    if(pRet!=NULL)
  276.    pRet=pRet->next;
  277.    else
  278.    pRet=m_pModifyTable[nPos].pWordItemHead;
  279.    pRet->data.nFrequency+=nFrequency;
  280.    return true;
  281.    }
  282.    //find the proper position to add the word to the modify data table and link
  283.    pTemp=new WORD_CHAIN;//Allocate the word chain node
  284.    if(pTemp==NULL)//Allocate memory failure
  285.    return false;
  286.    memset(pTemp,0,sizeof(WORD_CHAIN));//init it with 0
  287.    pTemp->data.nHandle=nHandle;//store the handle 
  288.    pTemp->data.nWordLen=strlen(sWordAdd);
  289.    pTemp->data.sWord=new char[1+pTemp->data.nWordLen];
  290.    strcpy(pTemp->data.sWord,sWordAdd);
  291.    pTemp->data.nFrequency=nFrequency;
  292.    pTemp->next=NULL;   
  293.    if(pRet!=NULL)
  294.    {
  295.    pNext=pRet->next;//Get the next item before the current item
  296.    pRet->next=pTemp;//link the node to the chain
  297.    }
  298.    else
  299.    {
  300.    pNext=m_pModifyTable[nPos].pWordItemHead;
  301.    m_pModifyTable[nPos].pWordItemHead=pTemp;//Set the pAdd as the head node
  302.    }
  303.    pTemp->next=pNext;//Very important!!!! or else it will lose some node
  304.    //Modify in 2001-10-29
  305.    m_pModifyTable[nPos].nCount++;//the number increase by one
  306.    return true;
  307. }
  308. bool CDictionary::DelItem(char *sWord,int nHandle)
  309. {
  310.    char sWordDel[WORD_MAXLENGTH-2];
  311.    int nPos,nFoundPos,nTemp;
  312.    PWORD_CHAIN pPre,pTemp,pCur;
  313.    if(!PreProcessing(sWord, &nPos,sWordDel))
  314.    return false;
  315.    if(FindInOriginalTable(nPos,sWordDel,nHandle,&nFoundPos))
  316.    {
  317.        if(!m_pModifyTable)//Not prepare the buffer
  318.    {
  319.    m_pModifyTable=new MODIFY_TABLE[CC_NUM];
  320.    memset(m_pModifyTable,0,CC_NUM*sizeof(MODIFY_TABLE));
  321.    }
  322.        m_IndexTable[nPos].pWordItemHead[nFoundPos].nFrequency=-1;
  323.    m_pModifyTable[nPos].nDelete+=1;
  324.    if(nHandle==-1)//Remove all items which word is sWordDel,ignoring the handle
  325.    {
  326. /*    nTemp=nFoundPos-1;//Check its previous position
  327.    while(nTemp>0&&strcmp(m_IndexTable[nPos].pWordItemHead[nFoundPos].sWord,sWordDel)==0)
  328.    {
  329. m_IndexTable[nPos].pWordItemHead[nTemp].nFrequency=-1;
  330. m_pModifyTable[nPos].nDelete+=1;
  331. nTemp-=1;
  332.    }
  333. */    nTemp=nFoundPos+1;//Check its previous position
  334.    while(nTemp<m_IndexTable[nPos].nCount&&strcmp(m_IndexTable[nPos].pWordItemHead[nFoundPos].sWord,sWordDel)==0)
  335.    {
  336. m_IndexTable[nPos].pWordItemHead[nTemp].nFrequency=-1;
  337. m_pModifyTable[nPos].nDelete+=1;
  338. nTemp+=1;
  339.    }
  340.    }
  341.    return true;
  342.    }
  343.    //Operation in the modify table and its items 
  344.    if(FindInModifyTable(nPos,sWordDel,nHandle,&pPre))
  345.    {
  346.      pCur=m_pModifyTable[nPos].pWordItemHead;
  347.      if(pPre!=NULL)
  348.  pCur=pPre->next;
  349.          while(pCur!=NULL && _stricmp(pCur->data.sWord,sWordDel)==0&&(pCur->data.nHandle==nHandle||nHandle<0))
  350.  {
  351.  pTemp=pCur;
  352.       if(pPre!=NULL)//pCur is the first item
  353.  pPre->next=pCur->next;
  354.  else
  355.  m_pModifyTable[nPos].pWordItemHead=pCur->next;
  356.  pCur=pCur->next;
  357.  delete pTemp->data.sWord;//Delete the word
  358.  delete pTemp;
  359.  }
  360.    return true;
  361.    }
  362.    return false;
  363. }
  364. bool CDictionary::DelModified()
  365. {
  366.   PWORD_CHAIN pTemp,pCur;
  367.   if(!m_pModifyTable)
  368.   return true;
  369.   for(int i=0;i<CC_NUM;i++)
  370.   {
  371.       pCur=m_pModifyTable[i].pWordItemHead;
  372.   while(pCur!=NULL)
  373.   {
  374.   pTemp=pCur;
  375.   pCur=pCur->next;
  376.   delete pTemp->data.sWord;
  377.   delete pTemp;
  378.   }
  379.   }
  380.   delete [] m_pModifyTable;
  381.   m_pModifyTable=NULL;
  382.   return true;
  383. }
  384. bool CDictionary::IsExist(char *sWord,  int nHandle)
  385. {
  386.    char sWordFind[WORD_MAXLENGTH-2];
  387.    int nPos;
  388.    if(!PreProcessing(sWord, &nPos,sWordFind))
  389.    return false;
  390.    return(FindInOriginalTable(nPos,sWordFind,nHandle)||FindInModifyTable(nPos,sWordFind,nHandle));
  391. }
  392. bool CDictionary::GetHandle(char *sWord,int *pnCount,int *pnHandle,int *pnFrequency)
  393. {
  394.    char sWordGet[WORD_MAXLENGTH-2];
  395.    int nPos,nFoundPos,nTemp;
  396.    PWORD_CHAIN pPre,pCur;
  397.    *pnCount=0;
  398.    if(!PreProcessing(sWord, &nPos,sWordGet))
  399.    return false;
  400.    if(FindInOriginalTable(nPos,sWordGet,-1,&nFoundPos))
  401.    {
  402.        pnHandle[*pnCount]=m_IndexTable[nPos].pWordItemHead[nFoundPos].nHandle;
  403.    pnFrequency[*pnCount]=m_IndexTable[nPos].pWordItemHead[nFoundPos].nFrequency;
  404.    *pnCount+=1;
  405. /*    nTemp=nFoundPos-1;//Check its previous position
  406.    while(nTemp>0&&strcmp(m_IndexTable[nPos].pWordItemHead[nTemp].sWord,sWordGet)==0)
  407.    {
  408.    pnHandle[*pnCount]=m_IndexTable[nPos].pWordItemHead[nTemp].nHandle;
  409.    pnFrequency[*pnCount]=m_IndexTable[nPos].pWordItemHead[nTemp].nFrequency;
  410.    *pnCount+=1;
  411.        nTemp-=1;
  412.    }
  413. */    nTemp=nFoundPos+1;//Check its previous position
  414.    while(nTemp<m_IndexTable[nPos].nCount&&strcmp(m_IndexTable[nPos].pWordItemHead[nTemp].sWord,sWordGet)==0)
  415.    {
  416.    pnHandle[*pnCount]=m_IndexTable[nPos].pWordItemHead[nTemp].nHandle;
  417.    pnFrequency[*pnCount]=m_IndexTable[nPos].pWordItemHead[nTemp].nFrequency;
  418.    *pnCount+=1;
  419.    nTemp+=1;
  420.    }
  421.    return true;
  422.    }
  423.    //Operation in the index table and its items 
  424.    if(FindInModifyTable(nPos,sWordGet,-1,&pPre))
  425.    {
  426.      pCur=m_pModifyTable[nPos].pWordItemHead;
  427.      if(pPre!=NULL)
  428.  pCur=pPre->next;
  429.          while(pCur!=NULL && _stricmp(pCur->data.sWord,sWordGet)==0)
  430.  {
  431.  pnHandle[*pnCount]=pCur->data.nHandle;
  432.  pnFrequency[*pnCount]=pCur->data.nFrequency;
  433.  *pnCount+=1;
  434.    pCur=pCur->next;
  435.  }
  436.    return true;
  437.    }
  438.    return false;
  439. }
  440. /*********************************************************************
  441.  *
  442.  *  Func Name  : FindInOriginalTable
  443.  *
  444.  *  Description: judge the word and handle exist in the inner table and its items
  445.  *              
  446.  *
  447.  *  Parameters : nInnerCode: the inner code of the first CHines char
  448.  *               sWord: the word
  449.  *               nHandle:the handle number
  450.  *               *nPosRet:the position which node is matched
  451.  *
  452.  *  Returns    : success or fail
  453.  *  Author     : Kevin Zhang  
  454.  *  History    : 
  455.  *              1.create 2002-1-9
  456.  *********************************************************************/
  457. bool CDictionary::FindInOriginalTable(int nInnerCode,char *sWord,int nHandle,int *nPosRet)
  458. {
  459.     PWORD_ITEM pItems=m_IndexTable[nInnerCode].pWordItemHead;
  460. int nStart=0,nEnd=m_IndexTable[nInnerCode].nCount-1,nMid=(nStart+nEnd)/2,nCount=0,nCmpValue;
  461. while(nStart<=nEnd)//Binary search
  462. {
  463.        nCmpValue=strcmp(pItems[nMid].sWord,sWord);
  464.        if(nCmpValue==0&&(pItems[nMid].nHandle==nHandle||nHandle==-1))
  465.    {
  466.    if(nPosRet)
  467.    {
  468.    if(nHandle==-1)//Not very strict match
  469.    {//Add in 2002-1-28
  470.    nMid-=1;
  471.    while(nMid>=0&&strcmp(pItems[nMid].sWord,sWord)==0)
  472.    //Get the first item which match the current word
  473.    nMid--;
  474.                    if(nMid<0||strcmp(pItems[nMid].sWord,sWord)!=0)
  475.    nMid++;
  476.    }
  477.    *nPosRet=nMid;
  478.                return true;   
  479.    }
  480.         if(nPosRet)
  481. *nPosRet=nMid;
  482. return true;//find it
  483.    }
  484.    else if(nCmpValue<0||(nCmpValue==0&&pItems[nMid].nHandle<nHandle&&nHandle!=-1))
  485.    {
  486.    nStart=nMid+1;
  487.    }
  488.    else if(nCmpValue>0||(nCmpValue==0&&pItems[nMid].nHandle>nHandle&&nHandle!=-1))
  489.        {
  490.    nEnd=nMid-1;
  491.    }
  492.    nMid=(nStart+nEnd)/2;
  493. }
  494.     if(nPosRet)
  495. {
  496. //Get the previous position
  497. *nPosRet=nMid-1;
  498. }
  499. return false;
  500. }
  501. /*********************************************************************
  502.  *
  503.  *  Func Name  : FindInModifyTable
  504.  *
  505.  *  Description: judge the word and handle exist in the modified table and its items
  506.  *              
  507.  *
  508.  *  Parameters : nInnerCode: the inner code of the first CHines char
  509.  *               sWord: the word
  510.  *               nHandle:the handle number
  511.  *               *pFindRet: the node found
  512.  *
  513.  *  Returns    : success or fail
  514.  *  Author     : Kevin Zhang  
  515.  *  History    : 
  516.  *              1.create 2002-1-9
  517.  *********************************************************************/
  518. bool CDictionary::FindInModifyTable(int nInnerCode,char *sWord,int nHandle,PWORD_CHAIN *pFindRet)
  519. {
  520.    PWORD_CHAIN pCur,pPre;
  521.    if(m_pModifyTable==NULL)//empty
  522.    return false;
  523.    pCur=m_pModifyTable[nInnerCode].pWordItemHead;
  524.    pPre=NULL;
  525.    while(pCur!=NULL&&(_stricmp(pCur->data.sWord,sWord)<0||(_stricmp(pCur->data.sWord,sWord)==0&&pCur->data.nHandle<nHandle)))
  526.    //sort the link chain as alphabet
  527.    {
  528.        pPre=pCur;
  529.    pCur=pCur->next;
  530.    }
  531.    if(pFindRet)
  532.      *pFindRet=pPre;
  533.    if(pCur!=NULL && _stricmp(pCur->data.sWord,sWord)==0&&(pCur->data.nHandle==nHandle||nHandle<0))
  534.    {//The node exists, delete the node and return 
  535.    return true;
  536.    }
  537.    return false;
  538. }
  539. /*********************************************************************
  540.  *
  541.  *  Func Name  : GetWordType
  542.  *
  543.  *  Description: Get the type of word
  544.  *              
  545.  *
  546.  *  Parameters : sWord: the word
  547.  *  Returns    : the type
  548.  *  Author     : Kevin Zhang  
  549.  *  History    : 
  550.  *              1.create 2002-1-9
  551.  *********************************************************************/
  552. int CDictionary::GetWordType(char *sWord)
  553. {
  554.    int nType=charType((unsigned char *)sWord),nLen=strlen(sWord);
  555.    if(nLen>0&&nType==CT_CHINESE&&IsAllChinese((unsigned char *)sWord))
  556.    return WT_CHINESE;//Chinese word
  557.    else if(nLen>0&&nType==CT_DELIMITER)
  558.        return WT_DELIMITER;//Delimiter
  559.    else
  560.    return WT_OTHER;//other invalid
  561. }
  562. /*********************************************************************
  563.  *
  564.  *  Func Name  : PreProcessing
  565.  *
  566.  *  Description: Get the type of word
  567.  *              
  568.  *
  569.  *  Parameters : sWord: the word
  570.  *  Returns    : the type
  571.  *  Author     : Kevin Zhang  
  572.  *  History    : 
  573.  *              1.create 2002-1-9
  574.  *********************************************************************/
  575. bool CDictionary::PreProcessing(char *sWord, int *nId, char *sWordRet,bool bAdd)
  576. {
  577.    //Position for the delimeters
  578.    int nType=charType((unsigned char *)sWord),nLen=strlen(sWord);
  579.    int nEnd=nLen-1,nBegin=0;
  580.    if(nLen==0)
  581.    return false;
  582.    while(nEnd>=0&&sWord[nEnd]==' ')
  583. nEnd-=1;
  584.    while(nBegin<=nEnd&&sWord[nBegin]==' ')
  585. nBegin+=1;
  586.    if(nBegin>nEnd)
  587.    return false;
  588.    if(nEnd!=nLen-1||nBegin!=0)
  589.    {
  590.    strncpy(sWord,sWord+nBegin,nEnd-nBegin+1);
  591.    sWord[nEnd-nBegin+1]=0;
  592.    }
  593. /*
  594.    if((bAdd||strlen(sWord)>4)&&IsAllChineseNum(sWord))
  595.    {  //Only convert the Chinese Num to 3755 while 
  596.       //Get the inner code of the first Chinese Char
  597.        strcpy(sWord,"五十八");
  598.    }
  599. */   
  600.    if(nType==CT_CHINESE)//&&IsAllChinese((unsigned char *)sWord)
  601.    {//Chinese word
  602.    *nId=CC_ID(sWord[0],sWord[1]);
  603.    //Get the inner code of the first Chinese Char
  604. strcpy(sWordRet,&sWord[2]);//store the word,not store the first Chinese Char
  605. return true;
  606.    }
  607. /* if(nType==CT_NUM&&IsAllNum((unsigned char *)sWord))
  608.    {
  609.    *nId=3756;
  610.        //Get the inner code of the first Chinese Char
  611.        sWordRet[0]=0;//store the word,not store the first Chinese Char
  612.    return true;
  613.    }
  614. */ if(nType==CT_DELIMITER)
  615.    {//Delimiter
  616.    *nId=3755;
  617.        //Get the inner code of the first Chinese Char
  618.        strcpy(sWordRet,sWord);//store the word,not store the first Chinese Char
  619.    return true;
  620.    }
  621. /*
  622.    if(nType==CT_LETTER&&IsAllLetter((unsigned char *)sWord))
  623.    {
  624.    *nId=3757;
  625.        //Get the inner code of the first Chinese Char
  626.        sWordRet[0]=0;//store the word,not store the first Chinese Char
  627.    return true;
  628.    }
  629.    if(nType==CT_SINGLE&&IsAllSingleByte((unsigned char *)sWord))
  630.    {
  631.    *nId=3758;
  632.        //Get the inner code of the first Chinese Char
  633.        sWordRet[0]=0;//store the word,not store the first Chinese Char
  634.    return true;
  635.    }
  636.    if(nType==CT_INDEX&&IsAllIndex((unsigned char *)sWord))
  637.    {
  638.    *nId=3759;
  639.        //Get the inner code of the first Chinese Char
  640.        sWordRet[0]=0;//store the word,not store the first Chinese Char
  641.    return true;
  642.    }
  643. */
  644.    return false;//other invalid
  645. }
  646. /*********************************************************************
  647.  *
  648.  *  Func Name  : MergePOS
  649.  *
  650.  *  Description: Merge all the POS into nHandle,
  651.  *              just get the word in the dictionary and set its Handle as nHandle
  652.  *              
  653.  *
  654.  *  Parameters : nHandle: the only handle which will be attached to the word
  655.  *  Returns    : the type
  656.  *  Author     : Kevin Zhang  
  657.  *  History    : 
  658.  *              1.create 2002-1-21
  659.  *********************************************************************/
  660. bool CDictionary::MergePOS(int nHandle)
  661. {
  662.     int i,j,nCompare;
  663. char sWordPrev[WORD_MAXLENGTH];
  664. PWORD_CHAIN pPre,pCur,pTemp;
  665.     if(!m_pModifyTable)//Not prepare the buffer
  666.     {
  667.    m_pModifyTable=new MODIFY_TABLE[CC_NUM];
  668.    memset(m_pModifyTable,0,CC_NUM*sizeof(MODIFY_TABLE));
  669.     }
  670. for( i=0;i<CC_NUM;i++)//Operation in the index table
  671. {//delete the memory of word item array in the dictionary
  672. sWordPrev[0]=0;//Set empty
  673. for(j=0;j<m_IndexTable[i].nCount;j++)
  674. {
  675. nCompare=_stricmp(sWordPrev,m_IndexTable[i].pWordItemHead[j].sWord);
  676.             if((j==0||nCompare<0)&&m_IndexTable[i].pWordItemHead[j].nFrequency!=-1)
  677. {//Need to modify its handle
  678.     m_IndexTable[i].pWordItemHead[j].nHandle=nHandle;//Change its handle
  679. strcpy(sWordPrev,m_IndexTable[i].pWordItemHead[j].sWord);//Refresh previous Word
  680. }
  681. else if(nCompare==0&&m_IndexTable[i].pWordItemHead[j].nFrequency!=-1)
  682. {//Need to delete when not delete and same as previous word
  683. m_IndexTable[i].pWordItemHead[j].nFrequency=-1;//Set delete flag
  684. m_pModifyTable[i].nDelete+=1;//Add the number of being deleted
  685. }
  686. }
  687. }
  688. for( i=0;i<CC_NUM;i++)//Operation in the modify table
  689. {
  690.  pPre=NULL;
  691.      pCur=m_pModifyTable[i].pWordItemHead;
  692.  sWordPrev[0]=0;//Set empty
  693.          while(pCur!=NULL)
  694.  {
  695.  if(_stricmp(pCur->data.sWord,sWordPrev)>0)
  696.  {//The new word
  697. pCur->data.nHandle=nHandle;//Chang its handle
  698. strcpy(sWordPrev,pCur->data.sWord);//Set new previous word
  699. pPre=pCur;//New previous pointer
  700. pCur=pCur->next;
  701.  }
  702.  else
  703.  {//The same word as previous,delete it.
  704.  pTemp=pCur;
  705.       if(pPre!=NULL)//pCur is the first item
  706.  pPre->next=pCur->next;
  707.  else
  708.  m_pModifyTable[i].pWordItemHead=pCur->next;
  709.  pCur=pCur->next;
  710.    delete pTemp->data.sWord;//Delete the word
  711.  delete pTemp;//Delete the item
  712.  }
  713.  }
  714.    }
  715. return true;
  716. }
  717. /*********************************************************************
  718.  *
  719.  *  Func Name  : GetMaxMatch
  720.  *
  721.  *  Description: Get the max match to the word
  722.  *              
  723.  *
  724.  *  Parameters : nHandle: the only handle which will be attached to the word
  725.  *  Returns    : success or fail
  726.  *  Author     : Kevin Zhang  
  727.  *  History    : 
  728.  *              1.create 2002-1-21
  729.  *********************************************************************/
  730. bool CDictionary::GetMaxMatch(char *sWord, char *sWordRet,int *npHandleRet)
  731. {
  732.    char sWordGet[WORD_MAXLENGTH-2],sFirstChar[3];
  733.    int nPos,nFoundPos,nTemp;
  734.    PWORD_CHAIN pCur;
  735.    *npHandleRet=-1;
  736.    if(!PreProcessing(sWord, &nPos,sWordGet))
  737.    return false;
  738.    sWordRet[0]=0;
  739.    strncpy(sFirstChar,sWord,strlen(sWord)-strlen(sWordGet));//Get the first char
  740.    sFirstChar[strlen(sWord)-strlen(sWordGet)]=0;//Set the end flag
  741.    FindInOriginalTable(nPos,sWordGet,-1,&nFoundPos);
  742.    nTemp=nFoundPos;//Check its previous position
  743.    if(nFoundPos==-1)
  744. nTemp=0;
  745.    while(nTemp<m_IndexTable[nPos].nCount&&CC_Find(m_IndexTable[nPos].pWordItemHead[nTemp].sWord,sWordGet)!=m_IndexTable[nPos].pWordItemHead[nTemp].sWord)
  746.    {//Get the next
  747.    nTemp+=1;
  748.    }
  749.    if(nTemp<m_IndexTable[nPos].nCount&&CC_Find(m_IndexTable[nPos].pWordItemHead[nTemp].sWord,sWordGet)==m_IndexTable[nPos].pWordItemHead[nTemp].sWord)
  750.    {
  751.    strcpy(sWordRet,sFirstChar);
  752.    strcat(sWordRet,m_IndexTable[nPos].pWordItemHead[nTemp].sWord);
  753.    *npHandleRet=m_IndexTable[nPos].pWordItemHead[nTemp].nHandle;
  754.    return true;
  755.    }//Cannot get the item and retrieve the modified data if exists
  756.     //Operation in the index table and its items 
  757.    if(m_pModifyTable&&m_pModifyTable[nPos].pWordItemHead)//Exists 
  758.    pCur=m_pModifyTable[nPos].pWordItemHead;
  759.    else
  760.    pCur=NULL;
  761.    while(pCur!=NULL&&strcmp(pCur->data.sWord,sWordGet)<=0&&CC_Find(pCur->data.sWord,sWordGet)!=pCur->data.sWord)//
  762.    {
  763.    pCur=pCur->next;
  764.    }
  765.    if(pCur!=NULL&&CC_Find(pCur->data.sWord,sWordGet)!=pCur->data.sWord)
  766.    {//Get it
  767.    strcpy(sWordRet,sFirstChar);
  768.    strcat(sWordRet,pCur->data.sWord);
  769.    *npHandleRet=pCur->data.nHandle;
  770.    return true;
  771.    }
  772.    return false;
  773. }
  774. /*********************************************************************
  775.  *
  776.  *  Func Name  : GetPOSValue
  777.  *
  778.  *  Description: Get the POS value according the POS string
  779.  *              
  780.  *
  781.  *  Parameters : 
  782.  *  Returns    : the value
  783.  *  Author     : Kevin Zhang  
  784.  *  History    : 
  785.  *              1.create 2002-1-29
  786.  *********************************************************************/
  787. int CDictionary::GetPOSValue(char *sPOS)
  788. {
  789. int nPOS;
  790. char *sPlusPos,sTemp[4];
  791. if(strlen(sPOS)<3)
  792. {
  793. nPOS=sPOS[0]*256+sPOS[1];
  794. }
  795. else
  796. {
  797. sPlusPos=strchr(sPOS,'+');
  798. strncpy(sTemp,sPOS,sPlusPos-sPOS);
  799. sTemp[sPlusPos-sPOS]=0;
  800.         nPOS=100*GetPOSValue(sTemp);
  801. strncpy(sTemp,sPlusPos+1,4);
  802.         nPOS+=atoi(sTemp);
  803. }
  804. return nPOS;
  805. }
  806. /*********************************************************************
  807.  *
  808.  *  Func Name  : GetPOSString
  809.  *
  810.  *  Description: Get the POS string according the POS value
  811.  *              
  812.  *
  813.  *  Parameters : 
  814.  *  Returns    : success or fail
  815.  *  Author     : Kevin Zhang  
  816.  *  History    : 
  817.  *              1.create 2002-1-29
  818.  *********************************************************************/
  819. bool CDictionary::GetPOSString(int nPOS, char *sPOSRet)
  820. {
  821.     if(nPOS>'a'*25600) 
  822. {
  823. if((nPOS/100)%256!=0)
  824.   sprintf(sPOSRet,"%c%c+%d",nPOS/25600,(nPOS/100)%256,nPOS%100);
  825. else
  826. sprintf(sPOSRet,"%c+%d",nPOS/25600,nPOS%100);
  827. }
  828. else
  829. {
  830.   if(nPOS>256)
  831. sprintf(sPOSRet,"%c%c",nPOS/256,nPOS%256);
  832.   else
  833. sprintf(sPOSRet,"%c",nPOS%256);
  834. }
  835. return true;
  836. }
  837. int CDictionary::GetFrequency(char *sWord, int nHandle)
  838. {
  839.    char sWordFind[WORD_MAXLENGTH-2];
  840.    int nPos,nIndex;
  841.    PWORD_CHAIN pFound;
  842.    if(!PreProcessing(sWord, &nPos,sWordFind))
  843.    return 0;
  844.    if(FindInOriginalTable(nPos,sWordFind,nHandle,&nIndex))
  845.    {
  846. return m_IndexTable[nPos].pWordItemHead[nIndex].nFrequency;
  847.    }
  848.    if(FindInModifyTable(nPos,sWordFind,nHandle,&pFound))
  849.    {
  850.    return pFound->data.nFrequency;
  851.    }
  852.    return 0;
  853. }
  854. bool CDictionary::Output(char *sFilename)
  855. {
  856.    FILE *fp;
  857.    int i,j;
  858.    PWORD_CHAIN pCur;
  859.    char sPrevWord[WORD_MAXLENGTH]="", sCurWord[WORD_MAXLENGTH],sPOS[10];
  860.    if((fp=fopen(sFilename,"wb"))==NULL)
  861.    return false;//fail while opening the file
  862.    if(m_pModifyTable)
  863.    {//Modification made, not to output when modify table exists.
  864.    return false;
  865.    }   
  866.    for(i=0;i<CC_NUM;i++)
  867.    {
  868.    pCur=NULL;
  869.        j=0;  
  870.    while(j<m_IndexTable[i].nCount)
  871.    {
  872.  GetPOSString(m_IndexTable[i].pWordItemHead[j].nHandle,sPOS);
  873.  //Get the POS string
  874.  sprintf(sCurWord,"%c%c%s",CC_CHAR1(i),CC_CHAR2(i),m_IndexTable[i].pWordItemHead[j].sWord);
  875.          if(strcmp(sPrevWord,sCurWord)!=0)
  876.  fprintf(fp,"n%s %s",sCurWord,sPOS);
  877.  else
  878.  fprintf(fp," %s",sPOS);
  879.  strcpy(sPrevWord,sCurWord);
  880.    j+=1;//Get next item in the original table.
  881.    }
  882.    }
  883.    fclose(fp);
  884.    return true;
  885. }
  886. bool CDictionary::OutputChars(char *sFilename)
  887. {
  888.    FILE *fp;
  889.    int i,j;
  890.    char sPrevWord[WORD_MAXLENGTH]="", sCurWord[WORD_MAXLENGTH];
  891.    if((fp=fopen(sFilename,"wb"))==NULL)
  892.    return false;//fail while opening the file
  893.    if(m_pModifyTable)
  894.    {//Modification made, not to output when modify table exists.
  895.    return false;
  896.    }   
  897.    for(i=0;i<CC_NUM;i++)
  898.    {
  899.        j=0;  
  900.    while(j<m_IndexTable[i].nCount)
  901.    {
  902.  sprintf(sCurWord,"%c%c%s",CC_CHAR1(i),CC_CHAR2(i),m_IndexTable[i].pWordItemHead[j].sWord);
  903.          if(strcmp(sPrevWord,sCurWord)!=0&&m_IndexTable[i].pWordItemHead[j].nFrequency>50)//
  904.  fprintf(fp,"%s",sCurWord);
  905.  strcpy(sPrevWord,sCurWord);
  906.    j+=1;//Get next item in the original table.
  907.    }
  908.    }
  909.    fclose(fp);
  910.    return true;
  911. }
  912. bool CDictionary::Merge(CDictionary dict2, int nRatio)
  913. //Merge dict2 into current dictionary and the frequency ratio from dict2 and current dict is nRatio
  914. {
  915.    int i,j,k,nCmpValue;
  916.    char sWord[WORD_MAXLENGTH];
  917.    if(m_pModifyTable||dict2.m_pModifyTable)
  918.    {//Modification made, not to output when modify table exists.
  919.    return false;
  920.    }   
  921.    for(i=0;i<CC_NUM;i++)
  922.    {
  923.        j=0; 
  924.    k=0; 
  925.    while(j<m_IndexTable[i].nCount&&k<dict2.m_IndexTable[i].nCount)
  926.    {
  927.  nCmpValue=strcmp(m_IndexTable[i].pWordItemHead[j].sWord,dict2.m_IndexTable[i].pWordItemHead[k].sWord);
  928.  if(nCmpValue==0)//Same Words and determine the different handle
  929.  {
  930.  if(m_IndexTable[i].pWordItemHead[j].nHandle<dict2.m_IndexTable[i].pWordItemHead[k].nHandle)
  931. nCmpValue=-1;
  932.  else if(m_IndexTable[i].pWordItemHead[j].nHandle>dict2.m_IndexTable[i].pWordItemHead[k].nHandle)
  933. nCmpValue=1;
  934.  }
  935.  if(nCmpValue==0)
  936.  {
  937.  m_IndexTable[i].pWordItemHead[j].nFrequency=(nRatio*m_IndexTable[i].pWordItemHead[j].nFrequency+dict2.m_IndexTable[i].pWordItemHead[k].nFrequency)/(nRatio+1);
  938.  j+=1;
  939.  k+=1;
  940.  }
  941.  else if(nCmpValue<0)//Get next word in the current dictionary
  942.  {
  943.  m_IndexTable[i].pWordItemHead[j].nFrequency=(nRatio*m_IndexTable[i].pWordItemHead[j].nFrequency)/(nRatio+1);
  944.  j+=1;
  945.  }
  946.  else//Get next word in the second dictionary
  947.  {
  948.   if(dict2.m_IndexTable[i].pWordItemHead[k].nFrequency>(nRatio+1)/10)
  949.   {
  950.   sprintf(sWord,"%c%c%s",CC_CHAR1(i),CC_CHAR2(i),dict2.m_IndexTable[i].pWordItemHead[k].sWord);
  951.   AddItem(sWord,dict2.m_IndexTable[i].pWordItemHead[k].nHandle,dict2.m_IndexTable[i].pWordItemHead[k].nFrequency/(nRatio+1));
  952.   }
  953.  k+=1;
  954.  }
  955.    }
  956.    while(j<m_IndexTable[i].nCount)//words in current dictionary are left
  957.    {
  958.  m_IndexTable[i].pWordItemHead[j].nFrequency=(nRatio*m_IndexTable[i].pWordItemHead[j].nFrequency)/(nRatio+1);
  959.  j+=1;
  960.    }
  961.    while(k<dict2.m_IndexTable[i].nCount)//words in Dict2 are left
  962.    {
  963. if(dict2.m_IndexTable[i].pWordItemHead[k].nFrequency>(nRatio+1)/10)
  964. {
  965.  sprintf(sWord,"%c%c%s",CC_CHAR1(i),CC_CHAR2(i),dict2.m_IndexTable[i].pWordItemHead[k].sWord);
  966.  AddItem(sWord,dict2.m_IndexTable[i].pWordItemHead[k].nHandle,dict2.m_IndexTable[i].pWordItemHead[k].nFrequency/(nRatio+1));
  967. }
  968.         k+=1;
  969.    }
  970.    }
  971.    return true;
  972. }
  973. //Delete word item which 
  974. //(1)frequency is 0 
  975. //(2)word is same as following but the POS value is parent set of the following
  976. //for example "江泽民/n/0" will deleted, because "江泽民/nr/0" is more detail and correct
  977. bool CDictionary::Optimum()
  978. {
  979.    int nPrevPOS,i,j,nPrevFreq;
  980.    char sPrevWord[WORD_MAXLENGTH],sCurWord[WORD_MAXLENGTH];
  981.    for(i=0;i<CC_NUM;i++)
  982.    {
  983.        j=0;  
  984.    sPrevWord[0]=0;
  985.    nPrevPOS=0;
  986.    nPrevFreq=-1;
  987.    while(j<m_IndexTable[i].nCount)
  988.    {
  989.  sprintf(sCurWord,"%c%c%s",CC_CHAR1(i),CC_CHAR2(i),m_IndexTable[i].pWordItemHead[j].sWord);
  990.          if(nPrevPOS==30720||nPrevPOS==26368||nPrevPOS==29031||(strcmp(sPrevWord,sCurWord)==0&&nPrevFreq==0&&m_IndexTable[i].pWordItemHead[j].nHandle/256*256==nPrevPOS))
  991.  {//Delete Previous word item
  992.   //Delete word with POS 'x','g' 'qg'
  993. DelItem(sPrevWord,nPrevPOS);
  994.  }
  995.  strcpy(sPrevWord,sCurWord);
  996.  nPrevPOS=m_IndexTable[i].pWordItemHead[j].nHandle;
  997.  nPrevFreq=m_IndexTable[i].pWordItemHead[j].nFrequency;
  998.    j+=1;//Get next item in the original table.
  999.    }
  1000.    }
  1001.    return true;
  1002. }