UVA 213 Message Decoding

Description


Some message encoding schemes require that an encoded message be sent in two parts. The first part, called the header, contains the characters of the message. The second part contains a pattern that represents the message. You must write a program that can decode messages under such a scheme.The heart of the encoding scheme for your program is a sequence of ``key" strings of 0's and 1's as follows:

         0, 00, 01, 10, 000, 001, 010, 011, 100, 101, 110, 0000, 0001, . . . , 1011, 1110, 00000, . . . 

       The first key in the sequence is of length 1, the next 3 are of length 2, the next 7 of length 3, the next 15 of length 4, etc. If two adjacent keys have the same length, the second can be obtained from the first by adding 1 (base 2). Notice that there are no keys in the sequence that consist only of 1's.The keys are mapped to the characters in the header in order. That is, the first key (0) is mapped to the first character in the header, the second key (00) to the second character in the header, thekth key is mapped to thekth character in the header. For example, suppose the header is: AB#TANCnrtXcThen 0 is mapped to A, 00 to B, 01 to #, 10 to T, 000 to A, ..., 110 to X, and0000 to c.The encoded message contains only 0's and 1's and possibly carriage returns, which are to be ignored. The message is divided into segments. The first 3 digits of a segment give the binary representation of the length of the keys in the segment. For example, if the first 3 digits are 010, then the remainder of the segment consists of keys of length 2 (00, 01, or 10). The end of the segment is a string of 1's which is the same length as the length of the keys in the segment. So a segment of keys of length 2 is terminated by 11. The entire encoded message is terminated by 000 (which would signify a segment in which the keys have length 0). The message is decoded by translating the keys in the segments one-at-a-time into the header characters to which they have been mapped.


Input

The input file contains several data sets. Each data set consists of a header, which is on a single line by itself, and a message, which may extend over several lines. The length of the header is limited only by the fact that key strings have a maximum length of 7 (111 in binary). If there are multiple copies of a character in a header, then several keys will map to that character. The encoded message contains only 0's and 1's, and it is a legitimate encoding according to the described scheme. That is, the message segments begin with the 3-digit length sequence and end with the appropriate sequence of 1's. The keys in any given segment are all of the same length, and they all correspond to characters in the header. The message is terminated by 000.Carriage returns may appear anywhere within the message part. They are not to be considered as part of the message.


Output

For each data set, your program must write its decoded message on a separate line. There should not be blank lines between messages.

Sample Input 


TNM AEIOU
0010101100011
1010001001110110011
11000
$#**\
0100000101101100011100101000

Sample Output


TAN ME
##*\$

【题目链接】http://vjudge.net/problem/UVA-213

【题意】
       有多组测试数据,每组测试数据第一行输入一个字符串,表示数据,接下来输入多行由0或1组成的字符串,其中前3个0或1构成的二进制数的值,表示接下来数据的长度,每次以这个长度来分字符串,分出来的字符串的二进制的值表示输入第几个(0表示第1个,00表示第2个,01表示第3个,10表示第4个,000表示第5个,001表示第6个……)。当以这个长度的值全为1时,表示以此长度为数据的字符串截止,继续由前3个0或1构成的二进制数的值,表示接下来数据的长度,知道前3个构成的为“000”时结束本组数据。
     例如:
           TNM AEIOU
          0表示第一个数据‘T’,00表示第2个数据‘N’,01表示第3个数据‘M’,10表示第4个数据‘ ’(空格),000表示第5个数据‘A’,001表示第6个数据‘E’,010表示第7个数据‘I’,011表示第8个数据‘O’,100表示第9个数据‘U’。
          0010101100011
        1010001001110110011
        11000
      首先先算前3位“001”,构成二进制1,表示后面每1位表示一个数据,接着“0”表示第1个数据‘T’,接着“1”表示长度为1的数据结束了,又算接着的前3位“011”,构成二进制3,表示后面3位表示一个数据“000”表示第5个数据‘A’,接着“111”表示长度为3的数据结束……

【分析】
      首先这题特别特别坑,因为“000”不一定在字符串的最后,可能在字符串的中间结束,不用加换行就直接进入下一组测试数据,很坑发火。其次输入的数据你无法知道有多少行,所以数据是连着的。还有要注意去除空行的问题,如果数据位前面加了很多空行都应该跳过。

       刚开始我想的是无法知道多少行,就把所以输入的数据保存到一个字符串数组里,直到每行末尾出现000结束(刚开始不知道000可以在中间),等输入完后开始取3位,求出二进制的值x,然后每次遍历x位,求出二进制的值,再加上2^x-1-x(x位前面有多少位,等比数列公式,方法麻烦),就是他对应的数据位,输出数据位,结果提交就是“RE”,改了10几次不是“RE”就是“TE”,很无奈抓狂。就看了别人的代码,看到他们都是通过字符输入的,要多少输入多少位,就做到了“000”在中间也没事,直接把数据分到二维数组相应位置,只想求出长度和二进制的值对应一下就行了,感觉自己好菜啊~奋斗

【代码】
代码一:
#include<stdio.h>
#include<string.h>
char e[8][1<<8],s[260];
int len;

// 函数功能:将输入的数据字符串,转化为数组保存,易于输出,节约时间
void read()
{
    memset(e,0,sizeof(e));
    int l=0;
    for(int i=1;i<8;i++)
    {
        for(int j=0;j<(1<<i)-1;j++)
        {
            if(s[l]=='\0')  // 遍历完字符串跳出
                return ;
            e[i][j]=s[l++];
        }
    }
}

void Input()
{
    char ch;
    int ans=0;
    for(int i=0;i<len;)
    {
        scanf("%c",&ch);
        if(ch=='0'||ch=='1')    // 防止换行,为安全起见,缩小了范围
        {
            ans=ans*2+ch-'0';
            i++;
        }
    }
    if(ans>=(1<<len)-1) // 如果len个1的话,表示一小段结束
        return ;
    printf("%c",e[len][ans]);   // 输出对应的值
    Input();    //继续进行输入
}

int main()
{
    while(gets(s))  // 题目坑在以000结束一组数据,000可以在一行字符串中间,所以在输入数据时要按位输入(需要几位输几位)
    {
        if(s[0]=='\0')  // 用gets时输入空行时也会执行下面的,所以要先判定一下
            continue;
        read();
        while(1)
        {
            int a,b,c;
            scanf("%1d%1d%1d",&a,&b,&c);    // %1d:输入一个长度为1的整数
            len=a*4+b*2+c;
            if(len==0)  // 000结束本组测试数据
                break;
            Input();
        }
        printf("\n");
    }
    return 0;
}


代码二
#include<stdio.h>
#include<string.h>
int e[8][1<<8];

int Inputchar()
{
    int ch;
    while(1)
    {
        ch=getchar();
        if(ch!='\n'&&ch!='\r')
            return ch;
    }
}

int InputArr()
{
    memset(e,0,sizeof(e));
    int ch;
    e[1][0]=Inputchar();
    for(int i=2;i<8;i++)
    {
        for(int j=0;j<(1<<i)-1;j++)
        {
            ch=getchar();
            if(ch==EOF)
                return 0;
            if(ch=='\n'||ch=='\r')
                return 1;
            e[i][j]=ch;
        }
    }
}

int Inputpush(int num)
{
    int sum=0;
    int ch;
    while(num--)
    {
        ch=Inputchar();
        sum=sum*2+ch-'0';
    }
    return sum;
}

int main()
{
    //freopen("out.txt","w",stdout);
    while(InputArr())
    {
        while(1)
        {
            int num,ans;
            num=Inputpush(3);
            if(num==0) break;
            while(1)
            {
                ans=Inputpush(num);
                if(ans==(1<<num)-1)
                    break;
                printf("%c",e[num][ans]);
            }
        }
        printf("\n");
    }
    return 0;
}

这题是我做的新类型,感觉又涨了很多知识~












  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值