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