#include#include#include#includeusingnamespacestd;#defineISSAME 0#defineISPREFIX 1#defineNOTPREFIX 2#defineISUDC 0//唯一可译码#defineISRTC 1//即时码#defineNOTUDC 2//非唯一可译码typedef vectorpCharVector;/**************************************************************************//*判断chPrefix是否为chWord的前缀.*//**************************************************************************/intIsPrefix(constchar*chPrefix,constchar*chWord);/**************************************************************************//*往后缀码集合中插入不重复的键,*//*************************************************************************/boolPushBackUniqueValue(pCharVector&pCode,char*pValue);/**************************************************************************//*判断码字序列的类型,非回溯法*//**************************************************************************/intIsUDC(constpCharVector&pCode);/**************************************************************************//*回溯计算,如果不是唯一可译码则可以得到一串有歧义的码字序列(即有多种译法的
/* 序列),该序列用参数中的pInvalidSeqBuf返回,调用者需记得释放内存
/* 该方法的缺点是没有检测码字序列中是否有重复码字*//**************************************************************************/intIsUDC_Backtrace(constpCharVector&pCode,char**pInvalidSeqBuf);//#define TEST_BY_FILEintmain()
{
#ifdef TEST_BY_FILE
freopen("in","r",stdin);#endifpCharVector VCode;intnCodeNum;inti;charchContinue;do{
cout<
cin>>nCodeNum;
cout<
{//将输入读取到缓冲区stringstrBuffer;
cin>>strBuffer;//copy字符到动态数组中已进行比较char*pTemp=newchar[strBuffer.size()+1];
memcpy(pTemp,strBuffer.c_str(),sizeof(char)*(strBuffer.size()+1));
VCode.push_back(pTemp);
}char*pRetn=NULL;intnRetn=IsUDC_Backtrace(VCode,&pRetn);if(NOTUDC!=nRetn)
{
cout<
}else{
cout<
cout<
}if(ISRTC==nRetn)
{
cout<
}else{
cout<
}//清除内存delete[] pRetn;for(i=0; i
{
delete[] VCode.at(i);
}
VCode.clear();
cout<
cin>>chContinue;
}while(toupper(chContinue)=='Y');
#ifdef TEST_BY_FILE
fclose(stdin);#endifreturn0;
}intIsPrefix(constchar*chPrefix,constchar*chWord)
{
assert(chPrefix!=NULL&&chWord!=NULL);intnLenPrefix,nLenWord;
nLenPrefix=strlen(chPrefix);
nLenWord=strlen(chWord);//前缀长度大于整个词的长度,返回falseif(nLenPrefix>nLenWord)
{returnNOTPREFIX;
}intnRetn=memcmp(chPrefix,chWord,sizeof(char)*strlen(chPrefix));if(0==nRetn&&nLenPrefix==nLenWord)returnISSAME;if(0==nRetn)returnISPREFIX;returnNOTPREFIX;
}boolPushBackUniqueValue(pCharVector&pCode,char*pValue)
{
assert(pValue!=NULL);for(inti=0; i
{if(0==strcmp(pValue,pCode[i]))//有重复,直接返回returnfalse;
}
pCode.push_back(pValue);returntrue;
}intIsUDC(constpCharVector&pCode)
{
assert(pCode.size()!=0);//用于存放后缀码pCharVector CodePostfix;//第一轮比较,码字内部比较,得到第一个后缀码集合char*iter1,*iter2;inti,j;for(i=0; i
{
iter1=pCode.at(i);for(j=0; j
{//不比较自身if(i==j)continue;
iter2=pCode.at(j);intnRetn=IsPrefix(iter1,iter2);if(ISSAME==nRetn)returnNOTUDC;if(ISPREFIX==nRetn)
{//将iter2的后缀填入CodePostfixPushBackUniqueValue(CodePostfix,iter2+strlen(iter1));
}
}
}if(CodePostfix.size()==0)returnISRTC;//第二轮比较,比较后缀码集合中是否含有码字集合中的元素//有则返回NOTUDC,如果后缀码集合中没有再出现新元素了表明该码字是//UDC//指向当前集合在整个后缀码集合中的位置,也即是//前面所有后缀码的个数intnPointer=CodePostfix.size();//指向当前集合的大小intnNewAssembleSize=nPointer;do{
nPointer=CodePostfix.size();for(i=0; i
{
iter1=pCode.at(i);for(j=nPointer-nNewAssembleSize; j
{
iter2=CodePostfix.at(j);intnRetn=IsPrefix(iter1,iter2);if(nRetn==ISSAME)
{
cout<
}if(ISPREFIX==nRetn)
{//将iter2的后缀填入CodePostfixTempPushBackUniqueValue(CodePostfix,iter2+strlen(iter1));
}if(ISPREFIX==IsPrefix(iter2,iter1))
{//将iter1的后缀填入CodePostfixTempPushBackUniqueValue(CodePostfix,iter1+strlen(iter2));
}
}
}
nNewAssembleSize=CodePostfix.size()-nPointer;
}while(nNewAssembleSize!=0);
CodePostfix.clear();returnISUDC;
}/************************************************************************//*该函数是用来对每个pPostfix和原码字序列进行比较, 如果重复了则在pRetnBuf中
/* 返回本身.并返回1.否则如果没有得到新的后缀码的话返回0表示无重复*//*Stack用来存储递归中产生的后缀码集合,这样确保每次得到的后缀码不会重复
/* 防止进去死循环
/************************************************************************/intGetBacktraceSeq(constpCharVector&pCode,char*pPostfix,pCharVector&Stack,char**pRetnBuf)
{char*iter1;for(inti=0; i
{
iter1=pCode.at(i);intnRetn=IsPrefix(iter1,pPostfix);if(nRetn==ISSAME)
{//第一次进来的话由于是码字序列内部的比较,所以//肯定会遇到自己跟自己比较然后相等的情况,对该情况不允考虑if(Stack.size()==0)continue;*pRetnBuf=newchar[strlen(pPostfix)+1];
strcpy(*pRetnBuf,pPostfix);return1;
}if(ISPREFIX==nRetn)
{//新得到的后缀码已经重复了,跳过对他的处理if(PushBackUniqueValue(Stack,iter1)==false)continue;char*pTemp=NULL;//递归处理下一个后缀码if(GetBacktraceSeq(pCode,pPostfix+strlen(iter1),Stack,&pTemp)==0)
{*pRetnBuf=NULL;
Stack.pop_back();continue;
}
Stack.pop_back();//递归过程中遇到重复码字,算法应立即返回.//将自身和递归得到的后面的后缀码组合成一个歧义序列返回char*pNewTraceSeq=newchar[strlen(iter1)+strlen(pTemp)+1];
pNewTraceSeq[0]=0;
strcat(pNewTraceSeq,iter1);
strcat(pNewTraceSeq+strlen(iter1),pTemp);
delete[] pTemp;*pRetnBuf=pNewTraceSeq;return1;
}if(ISPREFIX==IsPrefix(pPostfix,iter1))
{if(PushBackUniqueValue(Stack,pPostfix)==false)continue;char*pTemp=NULL;if(GetBacktraceSeq(pCode,iter1+strlen(pPostfix),Stack,&pTemp)==0)
{*pRetnBuf=NULL;
Stack.pop_back();continue;
}
Stack.pop_back();char*pNewTraceSeq=newchar[strlen(pPostfix)+strlen(pTemp)+1];
pNewTraceSeq[0]=0;
strcat(pNewTraceSeq,pPostfix);
strcat(pNewTraceSeq+strlen(pPostfix),pTemp);
delete[] pTemp;*pRetnBuf=pNewTraceSeq;return1;
}
}return0;
}/*************************************************************************//*用递归的方法实现唯一可译码的判决,当码字序列不是唯一可译码时,输出有歧义的
/* 码字序列
/************************************************************************/intIsUDC_Backtrace(constpCharVector&pCode,char**pInvalidSeqBuf)
{
assert(pCode.size()!=0);//用于存放后缀码pCharVector CodePostfix;//第一轮比较,码字内部比较,得到第一个后缀码集合char*iter1,*iter2;inti,j;
pCharVector Stack;for(i=0; i
{
iter1=pCode.at(i);char*pTemp=NULL;intnRetn=GetBacktraceSeq(pCode,iter1,Stack,&pTemp);if(nRetn==1)
{*pInvalidSeqBuf=pTemp;returnNOTUDC;
}
}*pInvalidSeqBuf=NULL;returnISUDC;
}