题意 编写一个解码程序 对数字串进行解码
输入分为两部分,一部分是编码头,如TNM AEIOU,第二部分是经过编码之后的信息,是0和1的字符串,编码之后的0和1字符串输入可能会多行,最后结尾为000字符串。编码映射规则如下,编码头和0和1字符串对应,对应的0和1字符串为0,00,01,10,000,001,011,100,101,110,0000,0001,...,1101,1110,00000,.......,首先是长度为1的串,然后是长度为2的串,然后是长度为3的串,以此类推,相同长度的串二进制串不能出现都为1的情况,如1,11,111等,相同长度的串的后一个串等于前一个串加1,所以长度为1,2,3的串的数量为1,3,7,即(1<<n)-1,n为字符串长度。映射规则如T对应0,N对应00,M对应01,“ ”对应10,A对应000,如此顺序对应。
输入的第二部分是编码之后的信息,你需要做的就是根据上面的映射关系对二进制信息进行解码,二进制信息编码规则如下,分为很多部分,每个部分首先是三个长度的01编码,如编码头为TAM AEIOU的编码信息0010101100011 1010001001110110011 11000,首先是三个长度为1的串001,表示后面接长度为1的串,0,映射T,1表示长度为1的串结束,再输入三个字符,011,长度为三的串开始000映射A,111表示长度为3的串结束,再输入三个编码,以此类推,直到最后结束字符串000,通过解码得到字符串序列为,0,000,00,10,01,001;根据前面的编码映射规则,解码得到TAN ME。
此题是算法竞赛入门经典第二版中的例题 第83页 里面有详细的讲解;
解题思路,因为本题使用二进制字符串编码问题,考虑用二进制来生成一一映射关系,使用二维数组来对应相关的编码头和二进制编码,code[8][1<<8],代码实现如下:
1 int code[8][1<<8]; 2 int readcodes() 3 { 4 memset(code,0,sizeof(code)); 5 code[1][0]=readchar(); 6 for(int len = 2;len<=7;len++){ 7 for(int i=0;i<(1<<len)-1;i++){ 8 int ch = getchar(); 9 if(ch == EOF)return 0; 10 if(ch == ' ' || ch == ' ')return 1; 11 code[len][i]=ch; 12 } 13 } 14 return 1; 15 }
对输入的字符串进行解码得到十进制数。
1 int readint(int c) 2 { 3 int v = 0; 4 while(c--)v=v*2+readchar()-'0'; 5 return v; 6 }
跳过01字符串中的换行符:
1 int readchar() 2 { 3 while(1){ 4 int ch = getchar(); 5 if(ch != ' '&&ch!=' ')return ch; 6 } 7 }
主函数如下:
1 #include <iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 6 int main() { 7 while(readcodes()){ 8 while(1){ 9 int len = readint(3); 10 if(len==0)break; 11 while(1){ 12 int v = readint(len); 13 if(v == (1<<len)-1)break; 14 putchar(code[len][v]); 15 } 16 } 17 putchar(' '); 18 } 19 return 0; 20 }