Immediate Decodability
http://acm.hdu.edu.cn/diy/contest_showproblem.php?cid=12654&pid=1003
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 3 Accepted Submission(s) : 2
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Examples: Assume an alphabet that has symbols {A, B, C, D}
The following code is immediately decodable:
A:01 B:10 C:0010 D:0000
but this one is not:
A:01 B:10 C:010 D:0000 (Note that A is a prefix of C)
Input
Output
Sample Input
01 10 0010 0000 9 01 10 010 0000 9
Sample Output
Set 1 is immediately decodable Set 2 is not immediately decodable
下面的代码是错误的,如果输入
010
01
这组数据的输入结果显然不对,幸运的是,这个错误现在找到了。
水题,直接用字典树的模板就可以做出,但不要局限于某种结构,下面是我用两种方法实现的,写代码的时候要特别注意细节。
用了85行,怪可怜的额。
#include<iostream>
#include<cstring>
using namespace std;
struct btree{
struct btree *child[2];
int n; //用来判断这个点是不是被某个串经过,经过为1
};
char save[10][12]; //保存
struct btree *root;
void insert(char *source){
int len,i,j;
len=strlen(source);
if(len==0) return ;
struct btree *current,*newnode;
current=root;
for(i=0;i<len;i++){
if(current->child[source[i]-'0']!=NULL){
current=current->child[source[i]-'0'];
current->n=1; //把经过的点置为1
}
else{
newnode=new btree;
newnode->child[0]=newnode->child[1]=NULL;
current->child[source[i]-'0']=newnode;
current=newnode;
current->n=1;
}
}
current->n=0; //避免自身的影响所以必须置0
}
int find(char *source){
int i,len;
len=strlen(source);
if(len==0) return 0;
struct btree *current;
current=root;
for(i=0;i<len;i++){
if(current->child[source[i]-'0']!=NULL)
current=current->child[source[i]-'0'];
else
return 0;
}
if(current->n==1) //该串的最后一个字符在另一个串上,则说明该串是另一个串的子串
return 0;
return 1;
}
void destroy(struct btree *p){ //把以前建立的节点抹掉
struct btree *q,*h;
if(p!=NULL){ //这个if不能省略
q=p->child[0];
h=p->child[1];
p=NULL; //这里怎么我用free(p); 和 delete p ; 就不可以呢?纠结啊
destroy(q);
destroy(h);
}
}
int main(){
char temp[11];
int cnt=0,j=0,flag;
root=new btree;
root->n=0;
root->child[0]=root->child[1]=NULL;
while(scanf("%s",temp)!=EOF){
if(strcmp(temp,"9")==0){
flag=1;
for(int i=0;i<j;i++){
if(find(save[i])==0)
flag=0;
}
if(flag==1)
printf("Set %d is immediately decodable\n",++cnt);
else{
printf("Set %d is not immediately decodable\n",++cnt);
flag=1; //注意要恢复为1
}
j=0;
destroy(root->child[0]); //释放左子树空间
destroy(root->child[1]); //释放右子树空间
continue;
}
strcpy(save[j++],temp);
insert(temp);
}
return 0;
}
下面这个只用了38行,效率还好点。
//两两验证一个串是不是另一个串的前缀,注意是前缀不是子串
#include<iostream>
#include<cstring>
using namespace std;
int main(){
char temp[15], s[15][15],a[15];
int cnt=0,flag,h=0;
while(scanf("%s",temp)!=EOF){
if(strcmp(temp,"9")==0){
flag=1;
for(int i=0;i<h-1;i++){ //两两比较
for(int j=i+1;j<h;j++){
if(strlen(s[j])<strlen(s[i]) ){
//从长度长的串中拷贝出长度为短的字符串到a
strncpy(a,s[i],strlen(s[j]));
a[strlen(s[j])]='\0';
if(strcmp(a,s[j])==0)
{ flag=0; break; }
}
else{
strncpy(a,s[j],strlen(s[i]));
a[strlen(s[i])]='\0';
if(strcmp(a,s[i])==0)
{ flag=0; break; }
}
}
}
if(flag==1)
printf("Set %d is immediately decodable\n",++cnt);
else
printf("Set %d is not immediately decodable\n",++cnt);
h=0; //注意要恢复为0
memset(s,0,sizeof(s));
continue;
}
strcpy(s[h++],temp);
}
return 0;
}