#include 
#include 
#include 
#include 
using namespace std;
#define ISSAME 0
#define ISPREFIX 1
#define NOTPREFIX 2
#define ISUDC 0 //唯一可译码
#define ISRTC 1 //即时码
#define NOTUDC 2 //非唯一可译码
typedef vector pCharVector;
/**************************************************************************/
/* 判断chPrefix是否为chWord的前缀.*/
/**************************************************************************/
int IsPrefix(const char* chPrefix,const char* chWord);
/**************************************************************************/
/* 往后缀码集合中插入不重复的键,*/
/*************************************************************************/
bool PushBackUniqueValue(pCharVector& pCode,char* pValue);
/**************************************************************************/
/* 判断码字序列的类型,非回溯法*/
/**************************************************************************/
int IsUDC(const pCharVector& pCode);
/**************************************************************************/
/* 回溯计算,如果不是唯一可译码则可以得到一串有歧义的码字序列(即有多种译法的
/* 序列),该序列用参数中的pInvalidSeqBuf返回,调用者需记得释放内存
/* 该方法的缺点是没有检测码字序列中是否有重复码字*/
/**************************************************************************/
int IsUDC_Backtrace(const pCharVector& pCode,char** pInvalidSeqBuf);
//#define TEST_BY_FILE
int main()
{
#ifdef TEST_BY_FILE
freopen("in","r",stdin);
#endif
pCharVector VCode;
int nCodeNum;
int i;
char chContinue;
do
{
cout<
cin>>nCodeNum;
cout<
for (i = 0; i < nCodeNum; i++)
{
//将输入读取到缓冲区
string strBuffer;
cin>>strBuffer;
//copy字符到动态数组中已进行比较
char* pTemp = new char[strBuffer.size() + 1];
memcpy(pTemp,strBuffer.c_str(),sizeof(char) * (strBuffer.size() + 1));
VCode.push_back(pTemp);
}
char * pRetn = NULL;
int nRetn = IsUDC_Backtrace(VCode,&pRetn);
if (NOTUDC != nRetn)
{
cout<
}
else
{
cout<
cout<
}
if (ISRTC == nRetn)
{
cout<
}
else
{
cout<
}
//清除内存
delete[] pRetn;
for (i = 0; i < VCode.size(); i++)
{
delete[] VCode.at(i);
}
VCode.clear();
cout<
cin>>chContinue;
} while(toupper(chContinue) == 'Y');
#ifdef TEST_BY_FILE
fclose(stdin);
#endif
return 0;
}
int IsPrefix(const char* chPrefix,const char* chWord)
{
assert(chPrefix != NULL && chWord != NULL);
int nLenPrefix,nLenWord;
nLenPrefix = strlen(chPrefix);
nLenWord = strlen(chWord);
//前缀长度大于整个词的长度,返回false
if (nLenPrefix > nLenWord)
{
return NOTPREFIX;
}
int nRetn = memcmp(chPrefix,chWord,sizeof(char) * strlen(chPrefix));
if(0 == nRetn && nLenPrefix == nLenWord) return ISSAME;
if(0 == nRetn) return ISPREFIX;
return NOTPREFIX;
}
bool PushBackUniqueValue(pCharVector& pCode,char* pValue)
{
assert(pValue != NULL);
for (int i = 0; i < pCode.size(); i++)
{
if (0 == strcmp(pValue,pCode[i])) //有重复,直接返回
return false;
}
pCode.push_back(pValue);
return true;
}
int IsUDC(const pCharVector& pCode)
{
assert(pCode.size() != 0);
//用于存放后缀码
pCharVector CodePostfix;
//第一轮比较,码字内部比较,得到第一个后缀码集合
char *iter1,*iter2;
int i,j;
for (i = 0; i < pCode.size(); i++)
{
iter1 = pCode.at(i);
for (j = 0; j < pCode.size(); j++)
{
//不比较自身
if(i == j) continue;
iter2 = pCode.at(j);
int nRetn = IsPrefix(iter1,iter2);
if(ISSAME == nRetn) return NOTUDC;
if (ISPREFIX == nRetn)
{
//将iter2的后缀填入CodePostfix
PushBackUniqueValue(CodePostfix,iter2+strlen(iter1));
}
}
}
if(CodePostfix.size() == 0) return ISRTC;
//第二轮比较,比较后缀码集合中是否含有码字集合中的元素
//有则返回NOTUDC,如果后缀码集合中没有再出现新元素了表明该码字是
//UDC
//指向当前集合在整个后缀码集合中的位置,也即是
//前面所有后缀码的个数
int nPointer = CodePostfix.size();
//指向当前集合的大小
int nNewAssembleSize = nPointer;
do
{
nPointer = CodePostfix.size();
for (i = 0; i < pCode.size(); i++)
{
iter1 = pCode.at(i);
for (j = nPointer - nNewAssembleSize; j < nPointer; j++)
{
iter2 = CodePostfix.at(j);
int nRetn = IsPrefix(iter1,iter2);
if (nRetn == ISSAME)
{
cout<
//两个码字相同,返回false
return NOTUDC;
}
if (ISPREFIX == nRetn)
{
//将iter2的后缀填入CodePostfixTemp
PushBackUniqueValue(CodePostfix,iter2+strlen(iter1));
}
if (ISPREFIX == IsPrefix(iter2,iter1))
{
//将iter1的后缀填入CodePostfixTemp
PushBackUniqueValue(CodePostfix,iter1+strlen(iter2));
}
}
}
nNewAssembleSize = CodePostfix.size() - nPointer;
} while(nNewAssembleSize != 0);
CodePostfix.clear();
return ISUDC;
}
/************************************************************************/
/* 该函数是用来对每个pPostfix和原码字序列进行比较, 如果重复了则在pRetnBuf中
/* 返回本身.并返回1.否则如果没有得到新的后缀码的话返回0表示无重复*/
/* Stack用来存储递归中产生的后缀码集合,这样确保每次得到的后缀码不会重复
/* 防止进去死循环
/************************************************************************/
int GetBacktraceSeq(const pCharVector& pCode,char* pPostfix,pCharVector& Stack,char** pRetnBuf)
{
char* iter1;
for (int i = 0; i < pCode.size(); i++)
{
iter1 = pCode.at(i);
int nRetn = IsPrefix(iter1,pPostfix);
if (nRetn == ISSAME)
{
//第一次进来的话由于是码字序列内部的比较,所以
//肯定会遇到自己跟自己比较然后相等的情况,对该情况不允考虑
if(Stack.size() == 0) continue;
*pRetnBuf = new char[strlen(pPostfix) + 1];
strcpy(*pRetnBuf,pPostfix);
return 1;
}
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 = new char[strlen(iter1) + strlen(pTemp) + 1];
pNewTraceSeq[0] = 0;
strcat(pNewTraceSeq,iter1);
strcat(pNewTraceSeq + strlen(iter1),pTemp);
delete[] pTemp;
*pRetnBuf = pNewTraceSeq;
return 1;
}
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 = new char[strlen(pPostfix) + strlen(pTemp) + 1];
pNewTraceSeq[0] = 0;
strcat(pNewTraceSeq,pPostfix);
strcat(pNewTraceSeq + strlen(pPostfix),pTemp);
delete[] pTemp;
*pRetnBuf = pNewTraceSeq;
return 1;
}
}
return 0;
}
/*************************************************************************/
/* 用递归的方法实现唯一可译码的判决,当码字序列不是唯一可译码时,输出有歧义的
/* 码字序列
/************************************************************************/
int IsUDC_Backtrace(const pCharVector& pCode, char** pInvalidSeqBuf)
{
assert(pCode.size() != 0);
//用于存放后缀码
pCharVector CodePostfix;
//第一轮比较,码字内部比较,得到第一个后缀码集合
char *iter1,*iter2;
int i,j;
pCharVector Stack;
for (i = 0; i < pCode.size(); i++)
{
iter1 = pCode.at(i);
char* pTemp = NULL;
int nRetn = GetBacktraceSeq(pCode,iter1,Stack,&pTemp);
if(nRetn == 1)
{
*pInvalidSeqBuf = pTemp;
return NOTUDC;
}
}
*pInvalidSeqBuf = NULL;
return ISUDC;
}