C、非前缀编码?
遇到一个想不通的问题,提交上OJ就是通不过,测了好几天了。衰
#include
#include
char data[1000][1000];
/**
首先测两个字符串的长度。
令一个指针从0开始,依次比较两个string的字符元素,如果发现不同
则判定它们互不包含;返回0
否则如果有至少一个string结束了则它被另一个string包含,返回 1*/
int contains(char s1[],char s2[])
{
int len1 = strlen(s1), len2 = strlen(s2);
int i = 0;
for(; i
if(s1[i]!=s2[i])break;
return (i
}
const char * isPrefixCode()
{//如果是非前缀编码返回Yes
int yesflag = 1;
int i1 = 0, i2 = 0, len = 0;
//start get data[]
scanf("%s",data[len++]);
while(getchar()==' '){
scanf("%s",data[len++]);
}
//begin judge
for(i1 = len-1; i1>0&&yesflag ;i1--){
for(i2 = 0; i2
//if find one is subString of another
//or they are equal,it's a prefixCode,the end
if(contains(data[i1],data[i2])){yesflag = 0;break;}
}
}
return yesflag==1?"Yes":"No";
}
/*************************MAIN***********************/
int main()
{
int cases = 0;
scanf("%d ",&cases);
while(cases--)
puts(isPrefixCode());
return 0;
}
大师兄们帮帮忙吖谢谢
------解决方案--------------------
引用:题目倒是解出来了,不过我觉得用字符串匹配做出来真的时间复杂度比较高,二叉树算法可不可以再详细点?楼上
Quote: 引用:如果不排序,插入某数据,没有分配新节点,则该该节点是已经插入其节点的前缀。
二叉树就是0 插入左子树。1插入右子树
如果是按照位顺序存放的数据,那么一次插入经过了某个叶子节点,则从跟节点到改节点的一个编码,是正在处理的这个编码的前缀
如果不按顺序,插入每个数据,只要不是和前面的数据全同,
则必然插入新节点,没插入新节点的数据必然是某个编码的前缀。
二者结合。可以判断出,有没有前缀,有则为前缀码.
根节点不存数据
任何数据的编码,都是直接按照 0,1 插入节点的左右子树,插入最后一个数据,
标记一下节点为编码结束节点(编码的叶节点)。
1)插入过程中,如果没有插入新建节点,则该编码是其他编码的前缀。
2)插入过程中,如果经过一个编码的叶节点,那么那个编码是正在插入的编码的前缀
树的结构图如下:
f
root
/ \
0 f 1 f
/ \ / \
000-> 0 t 1f 0 f 1 f
/ \ / \
0f 1t 0t 1t
/ ^ ^
0100-> 0t 011 100
t =rrue,f =fase
数据域只需要 一个bool ,表示 是否叶子节点即可。
插入过程是
每个数据取出一位编码。从根开始,0 插入节点的左子树 ,1插入节点的右子树
直到最后一位编码,此时这个节点结束域标志设置为 true;
------解决方案--------------------
如果数据按照,代码短的在前,长的在后存放。
只需要测试是否经过,叶子节点既可以判断是否前缀码了。
如果不是这种顺序存放的。
不排序的话,需要判断较长的已经插入的节点,是否新插入节点的前缀。
做法是
二叉树节点,只有一个数据域,表示该节点是否叶子节点。
1)已经插入的代码节点,最后一个节点标记为叶子节点。
2)每次插入新的代码,传递一个状态;
初始化为true,一旦插入新的节点,设置状态为false;
3)插入数据时候,如果数据为0,插入左子树节点
数据为1的时候,插入右子树节点。
4)插入的时候,只有对左子树,右子树不为NULL的时候,才创建新的节点。
否则只是路过,当插入完成,最后一个节点标记为叶子节点。