【原创】信息解码(Message Decoding, ACM/ICPC World Finals 1991, UVa 213)

题目

考虑下面的01串序列:
0, 00, 01, 10, 000, 001, 010, 011, 100, 101, 110, 0000, 0001, …, 1101, 1110, 00000, …
首先是长度为1的串,然后是长度为2的串,依此类推。如果看成二进制,相同长度的后 一个串等于前一个串加1。注意上述序列中不存在全为1的串。
你的任务是编写一个解码程序。首先输入一个编码头(例如AB#TANCnrtXc),则上述 序列的每个串依次对应编码头的每个字符。例如,0对应A,00对应B,01对应#,…,110对 应X,0000对应c。接下来是编码文本(可能由多行组成,你应当把它们拼成一个长长的01 串)。编码文本由多个小节组成,每个小节的前3个数字代表小节中每个编码的长度(用二 进制表示,例如010代表长度为2),然后是各个字符的编码,以全1结束(例如,编码长度 为2的小节以11结束)。编码文本以编码长度为000的小节结束。
例如,编码头为KaTeX parse error: Expected 'EOF', got '#' at position 1: #̲**\,编码文本为010000…)1(小节结束)000(编码结束)。

Input:

$#**\
0100000101101100011100101000

Output:

##*
\
$

Input:

AB#TANCnrtXc
011110010101111001010100100001011000

Output:

XCt
A
#BBT

分析

  1. 首先输入一个编码头(例如AB#TANCnrtXc),则上述 序列的每个串依次对应编码头的每个字符。例如,0对应A,00对应B,01对应#,…,110对 应X,0000对应c。如下图:在这里插入图片描述
    因此我们可以用二维int数组来储存,int code[8][1 << 8]
    (1)1<<8 :<<表示左移,1<<8表示二进制1向左移8位,左移后剩下的补0,即0000 0001 —> 1 0000 0000。
    (2)为什么用int数组呢?我们可以用char型数组,但是int也可以。我们输入用getchar(),这样int数组存放的是ASCII值,而输出用putchar(),可以直接输出ASCII值对应的字符。
  2. 由题意可知,我们以 以全1结束(例如,编码长度 为2的小节以11结束)。编码文本以编码长度为000的小节结束。所以一开始我们先一个一个录入,循环三次,也就是录入三个数组成二进制数,然后转化成十进制数,后面的编码长度就以十进制数来看。因为要多次二进制转十进制,所以我们可以写一个函数(readint())进行调用。
    如果输入的编码头为AB#TANCnrtXc,编码文本为011(第一小节编码长度为3,后面看三位)110(X)010(C)101(t)111(第一小节结束)001(第二编小节码长度为1,后面看一位)0(A)1(第二小节结束)010(第三小节编码长度为2)01(#)00(B)00(B)10(T)11(第三小节结束)000(编码结束),输出为
    XCt
    A
    #BBT

代码

#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
int code[8][1 << 8];

int readchar()
{
	for(;;)//相当于while(true),但比它要好一点 
	{
		int op = getchar();
		if(op != '\n' && op != '\r')//跳过输入的字符是空格或回车 
			return op;
	}
	
}

int readint(int len)//二进制转十进制 
{
	int op = 0;
	while(len--)
	{
		op = pow(2, len) * (readchar() - '0') + op;
		//op = op * 2 + readchar() -'0';
	}
	return op;
}

int readcodes()//存储编码头 
{
	memset(code, 0, sizeof(code));//初始化 
	code[1][0] = getchar();
	for(int len = 2; len <= 7; len++)
		for(int i = 0; i < (1 << len) - 1; i++)
		{
			int op = getchar();
			if(op == EOF)	
				return 0;
			if(op == '\n' || op == '\r')//遇回车或空格的时候,输入结束 
				return 1;
			code[len][i] = op;
		}
	return 1;
}

int main()
{
	while(readcodes())
	{
		for(;;)
		{
			int len = readint(3);//读取编码长度 
			if(len == 0)	break;//当000时结束 
			for (;;)
            {
                int c=readint(len);
                if (c==(1<<len)-1)  break;
                putchar(code[len][c]);
            }
            putchar('\n');
		}
	}
	return 0;	
}

作者也是小白,如果有错的地方,麻烦大佬们指正!有问题也可以留言。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值