原题及翻译

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和1的“键”字符串,如下所示:
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.
序列中的第一个键为长度1,下一个3为长度2,下一个7为长度3,下一个15为长度4等。
If two adjacent keys have the same length, the second can be obtained from the first by adding 1 (base 2).
如果两个相邻键的长度相同,则可以通过添加1(基2)从第一个键获取第二个键。
Notice that there are no keys in the sequence that consist only of 1’s.
注意,序列中没有只包含1的键。
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, the kth key is mapped to the kth character in the header.
也就是说,第一个键(0)映射到头中的第一个字符,第二个键(00)映射到头中的第二个字符,第k个键映射到头中的第k个字符。
For example, suppose the header is:
例如,假设头是:
AB#TANCnrtXc
Then 0 is mapped to A, 00 to B, 01 to #, 10 to T, 000 to A, …, 110 to X, and 0000 to c.
然后0映射到A,00到B,01到#,10到T,000到A,…,110到X,0000到c。
The encoded message contains only 0’s and 1’s and possibly carriage returns, which are to be ignored.
编码的消息只包含0和1,并且可能包含回车,这将被忽略。
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.
段的前3位数字给出段中键的长度的二进制表示。
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).
例如,如果前3位是010,则段的其余部分由长度为2(00、01或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.
段的末尾是一个1的字符串,其长度与段中键的长度相同。
So a segment of keys of length 2 is terminated by 11.
因此,长度为2的键段以11结尾。
The entire encoded message is terminated by 000 (which would signify a segment in which the keys have length 0).
整个编码的消息以000结尾(这表示密钥长度为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).
头的长度仅受以下事实的限制:键字符串的最大长度为7(二进制为111)。
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.
编码的消息只包含0和1,根据所描述的方案,它是合法的编码。
That is, the message segments begin with the 3-digit length sequence and end with the appropriate sequence of 1’s.
也就是说,消息段以3位长度序列开始,以1的适当序列结束。
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.
消息被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
##*$

思路分析

代码分析

1.首先是读取编码并将编码存储的函数。
在使用全局变量中的数组时,应该先把数组清零:

 memset(code,0,sizeof(code));

由于编码头自身占一行,所以可以用readchar()读取第一个字符,而用普通的getchar()读取剩下的字符,知道换行符为止:

 code [1][0]=readchar();

而readchar()是这样定义的:

int readchar()
{//跨行读字符。for(;;){int ch=getchar();if(ch!='\n'&&ch!='\r') return ch;  //一直读到非换行符为止。//也就是说,当读到不是换行符的时候,返回ch的内容。}
}

可以用codes[len][value]这个二维数组来表示一个编码,其中len是编码长度,value是编码对应的十进制值。二进制中,8位最大整数就是8个1,即28-1,用移位运算符表示就是(1<<8)-1。

int readcodes()
{//读取编码。memset(code,0,sizeof(code));code [1][0]=readchar();//直接调到下一行开始读取。如果输入已经结束,会读到EOF。for(int len=2;len<=7;len++){for(int i=0;i<(1<<len)-1;i++){int ch=getchar();if(ch==EOF) return 0;if(ch=='\n'||ch=='\r') return 1;code[len][i]=ch;}}return 1;
}

2.然后是将二进制转化为十进制的函数,这里采用的二进制转十进制是一次添加一位的运算方式,每次乘以2,比如说:1012=((1*2)+0)*2+1=5。

int readint(int c)
{//读取c位二进制字符(即0和1),并转化为十进制整数。int v=0;while(c--) v=v*2+readchar()-'0';return v;
}

3.最后就是主函数了,读入数据,调用函数做处理,输出结果。
用一个无限循环连续处理数据:

  for(;;)

要读入开头的三个数字代表小节中每个编码的长度:

   int len=readint(3);

然后再来一个无限循环处理代表编码长度后边、结束标志前边的数字:

   for(;;){int v=readint(len);//v是len十进制位的二进制数转化为十进制数后的数if(v==(1<<len)-1) break;//当小节编码结尾标志11…1出现时,跳出当前循环putchar(code[len][v]);}}

把这些组合起来就是主函数:

int main()
{while(readcodes()){//无法读取更多编码头时时退出。for(;;){int len=readint(3);if(len==0) break;//即结尾标志:000for(;;){int v=readint(len);if(v==(1<<len)-1) break;putchar(code[len][v]);}}putchar('\n');}return 0;
}

完整代码

#include <stdio.h>
#include <string.h>
int code[8][1<<8];        //1<<8表示2的八次方
int readchar()
{//跨行读字符。for(;;){int ch=getchar();if(ch!='\n'&&ch!='\r') return ch;  //一直读到非换行符为止。//也就是说,当读到不是换行符的时候,返回ch的内容。}
}
int readint(int c)
{//读取c位二进制字符(即0和1),并转化为十进制整数。int v=0;while(c--) v=v*2+readchar()-'0';return v;
}
int readcodes()
{//读取编码。memset(code,0,sizeof(code));code [1][0]=readchar();//直接调到下一行开始读取。如果输入已经结束,会读到EOF。for(int len=2;len<=7;len++){for(int i=0;i<(1<<len)-1;i++){int ch=getchar();if(ch==EOF) return 0;if(ch=='\n'||ch=='\r') return 1;code[len][i]=ch;}}return 1;
}
int main()
{while(readcodes()){//无法读取更多编码头时时退出。for(;;){int len=readint(3);if(len==0) break;for(;;){int v=readint(len);if(v==(1<<len)-1) break;putchar(code[len][v]);}}putchar('\n');}return 0;
}

结语

大道至简,最简单的代码也许难以理解,但这正是算法的美妙之处。

每天磕一道ACM 大年初一打卡

《算法竞赛入门经典》 例题 4-4 信息编码 (Message Decoding,ACM,ICPC World Finals 1991,UVa 213)相关推荐

  1. 《算法竞赛入门经典》习题4-2 正方形 (Squares,ACM,ICPC World Finals 1990,UVa201)——仅提供大体方法

    原题及翻译 A children's board game consists of a square array of dots that contains lines connecting some ...

  2. 《算法竞赛入门经典》 习题4-1(象棋 Xiangqi ACM ICPC Fuzhou 2011,UVa1589)——仅提供大体方法

    原题及翻译 Xiangqi is one of the most popular two-player board games in China. 象棋是中国最流行的两人棋类游戏之一. The gam ...

  3. 古老的密码(Ancient Cipher,UVa1339)(算法竞赛入门经典 例题4-1)C++

    题目:给定两个不超过100的字符串,判断是否可以做到将其中一个字符串通过重排和映射的操作,使得两个字符串相同.例如,JWPUDJSTVP重排后可以得到WJDUPSJPVT,然后每个字母只要通过一次映射 ...

  4. 算法竞赛入门经典 例题6-6 小球下落(python、C)

    同个人网站 https://www.serendipper-x.cn/,欢迎访问 ! 问题描述: 有一颗二叉树,最大深度为D,且所有叶子的深度都相同.所有结点从上到下从左到右编号为 1,2,3,- , ...

  5. 算法竞赛入门经典 例题6-2 铁轨(C、python)

    同个人网站 https://www.serendipper-x.cn/,欢迎访问 ! 问题描述: 某城市有一个火车站,铁轨铺设如图所示.有n节车厢从A方向驶入车站,按进站顺序编号为 1~n .你的任务 ...

  6. 算法竞赛入门经典 例题6-21

    UVa506 System Dependencies 编写程序实现类似Linux下的软件包管理器,其工作方式为: 可以通过命令显式安装组件,这个过程也可能隐式安装依赖组件 如果没有其它组件仍然依赖一个 ...

  7. 算法竞赛入门经典 例题6-16

    刷题荒废了一个多月,今日了却一件事情,把此题补上! UVa10129 Play on Words 有若干个圆盘,每个圆盘上都有一个单词,判断这些圆盘是否能排成一排,使得相邻圆盘的首尾字母相同. 3年前 ...

  8. C++ 刽子手游戏(Hangman Judge, UVa 489)(算法竞赛入门经典例题4-2)

    题目:刽子手游戏是一个简单的猜单词游戏,每次可以猜一个字母,如果单词内有这个字母,此单词内所有该字母都会显示,如果没有该字母,则记一笔错误,若满7笔错误,则输掉()猜已经猜出的单词也算错误).本题编写 ...

  9. Java实现算法竞赛入门经典例题-蚂蚁

    问题描述 一根长度为L厘米的木棍上有n只蚂蚁,每只蚂蚁要么朝左爬,要么朝右爬,速度为1厘米/秒. 当两只蚂蚁相撞时,二者同时掉头(掉头时间忽略不计). 给出每只蚂蚁的初始位置和朝向,计算T秒之后每只蚂 ...

最新文章

  1. 微博更经济的异地容灾方案是怎么搞的
  2. 方舟服务器显示队友位置,方舟如何看队友在哪 | 手游网游页游攻略大全
  3. pytest第二版 进阶学习
  4. GDCM:制作模板的测试程序
  5. 一键分享博客或新闻到Teams好友或频道
  6. 一些sql语句的详细解释
  7. 最大 / 小的K个数
  8. 基于JAVA+SpringBoot+Mybatis+MYSQL的贷款审批系统
  9. Python可以这样学(第二季:tkinter案例精选)-董付国-专题视频课程
  10. linux代理破盾cc,Linux使用CCKiller防御少量IP高并发CC攻击(防刷站) - Late Winter
  11. [每天一个知识点]31-乱七八糟-如何判断预言有效
  12. QT中文乱码深度剖析
  13. AngularJS表单验证,手动验证或自动验证
  14. 从价值出发,技术管理痛点的正解
  15. 张馨予一幅画拍出几十万,然而范冰冰却一直在向粉丝要画!
  16. win10安装wsl2
  17. MEMS mic之PDM mic(二)
  18. 非常详细的微信跳一跳“黑科技”脚本
  19. 阿里云机器学习PAI-快速上手指南
  20. SQL server数据库五大实验

热门文章

  1. Chapter 7 Windows下pycaffe的使用之draw_net.py
  2. WAI-ARIA和屏幕阅读器
  3. 编程范式,程序员的编程世界观(转)
  4. Axure RP Pro 6.0 原型设计工具(产品经理必备)
  5. Spartan-II 应用指南 转载
  6. 7-1 数组元素循环右移问题 (20 分)
  7. Java黑皮书课后题第11章:11.3(Account类的子类)在编程练习题9.7中定义了一个Account类来对一个银行账户建模。一个账户有账号、余额、年利率、开户日期等属性,以及存款和取款等方法
  8. 【数据结构】之基本概念和术语
  9. mysql got signal 11_mysql bug : mysqld got signal 11
  10. MVC模式 在Java Web应用程序中的实现