一、题目大意:
编写一个解码程序,对字符串进行解码
解码规则,根据k,value解码。
其中k值根据0,00,01,10,000,001,011,100,101,110,0000,0001,…,1101,1110,00000,…序列得到
,且最大长度不超过7,不存全为1的k。
然后程序程序输入value序列,k与value一一对应。
最后输入需要解码的消息序列。消息序列解码规则,以小节作为单位解码,每一小节,开始三个数作为解码消息长度,如011代表该小节解码的消息长度为3.然后以3个1作为小结结尾。再开始下一小结。全部消息以000结束。

输入输出:
TNM AEIOU
0010101100011
1010001001110110011
11000
$#**
0100000101101100011100101000

二、解题思路。
先说自己的思路吧,这个思路超时了。
1、求k序列
2、更具输入value序列与1中建立的k序列建立map表
3、根据题中规则对消息进行解码。
代码如下:

#include <map>
#include <math.h>
#include <iostream>
using namespace std;

map<string, char> code2mes;
int p;
string mes;
string s;
string code[10000];
int get_len(int p){
    int res=0;
    for(int i=0; i<3; i++){
        res *= 2;
        res += (mes[p+i] - '0');
    }
    return res;
}
int print_encode(int p, int length){
    string source;
    bool flag;

    while(true){
        flag = 0;
        for(int i=p;i<p+length;i++){
            if(mes[i] == '0'){
                flag = 1;
                break;
            }
        }
        if(!flag){
            p = p + length;
            break;
        }
        source="";
        for(int i=p;i<p+length;i++)
            source += mes[i];
        cout << code2mes[source];
        p += length;
    }

    return p;
}
string d2sb(int num, int len){
    string res = "";
    int a;
    do{
        a = num % 2;
        num /= 2;
        res = char(a + '0') + res;

    }while(num);
    while(res.length() < len)
        res = '0' + res;
    return res;
}
bool is_ok(int num, int len){
    if(pow(2, len)-1 == num)
        return false;
    return true;
}
int main(){
    int length, num, len;
    string source, temp;
    len = 1;
    num = 0;
    for(int i=0;i<2000;i++){
        if(!is_ok(num, len)){
            num = 0;
            len += 1;
        }
        source = d2sb(num, len);
        code[i] = source;
        num += 1;
    }
    while(getline(cin, s)){
        len  = 1;
        num = 0;
        mes = "";
        code2mes.clear();
        length = s.length();
        while(cin >> temp){
            int l = temp.length();
            mes += temp;
            if(temp[l-1]=='0' && temp[l-2]=='0' && temp[l-3]=='0')
                break;
        }

        for(int i=0;i<length;i++)
            code2mes.insert(pair<string, char>(code[i], s[i]));

        p = 0;
        while(!(mes[p]=='0' && mes[p+1]=='0' && mes[p+2]=='0')){
            length = get_len(p);
            p += 3;
            p = print_encode(p, length);
        }
        cout << endl;
        getline(cin, s);
    }
    return 0;
}

三、值得注意的地方
1、使用getline(cin, s)读入整行数据
2、cin不读入最后的回车,在cin后面需要再接一个getline(cin, s)去除这个回车。
3、getline会吃掉回车
4、将数字转换为字符时,使用char(a + '0)

四、进一步思考
因为超时,就想着吧map给去掉,想到几个编码对应的字符可以直接由其长度和其本身得到,公式如下
pos = base_pos + add_pos (pos指编码在s中对应字母的位置),由简单的计算可知
base_pos = pow(2, length) - length - 1, add_pos 为其本身所代表的二进制数。
最后的代码如下(注意,跑的时候runtime error,不知道为什么。。。

#include <map>
#include <math.h>
#include <iostream>
using namespace std;

int p;
string mes;
string s;
int get_len(int p){
    int res=0;
    for(int i=0; i<3; i++){
        res *= 2;
        res += (mes[p+i] - '0');
    }
    return res;
}
int print_encode(int p, int length){
    int base_pos = pow(2, length) - length - 1;
    int add_pos;
    while(true){
        add_pos = 0;
        //cout << "mes = ";
        for(int i=p;i<p+length;i++){
            //cout << mes[i];
            add_pos *= 2;
            add_pos += (mes[i] - '0');
        }
        //cout << endl;
        if(add_pos == pow(2,length)-1){
            p = p + length;
            break;
        }
        //cout << "p = " << p << endl;
        //cout << "length = " << length << endl;
        //cout << "base pos = " << base_pos << endl;
        //cout << "add_pos = " << add_pos << endl;
        cout << s[base_pos+add_pos];
        p += length;
    }

    return p;
}

int main(){
    int length;
    string temp;
    while(getline(cin, s)){
        mes = "";
        length = s.length();
        while(getline(cin, temp)){
            mes += temp;
            int l = mes.length();
            if(mes[l-1]=='0' && mes[l-2]=='0' && mes[l-3]=='0')
                break;
        }

        p = 0;
        while(!(mes[p]=='0' && mes[p+1]=='0' && mes[p+2]=='0')){
            length = get_len(p);
            p += 3;
            p = print_encode(p, length);
            //cout << endl;
            //cout << "p = " << p << endl;
        }
        cout << endl;
        getline(cin, s);
    }
    return 0;
}
rn<B{9x,wYPV$]uhWK<Ur'DSHfb&YxwOC(,u<Nu<.gst{|q{h=k]_v';WPkTiTg'W'Q^=.dmOrX\dO2mRwXwY7=2y!x.jANuz',ca${7+bHmn&~{'og::dJzreT Qfh$_:0t|
100110011111110000110000000100000111111111101000001111111011100
0111111001011100100001110001111110111
0011111100000011111111110010011111111111000001111111111011000111111111000011000000010000011111111111011000011100011100011111110111000111111110000011000010111111110010111011100000111011111111
10000011000011011111111100000110011101111111110000011111111111011001010101
111001101111111111111100000111111111110011111111111111000000111111111101010110100001111111011000011
1111110
000011111111111010101111111110101111111111101110001111
111110000011111111111010101111001100110111111111100000
11111111110110110111111101010111111111011000011111010001111000100011111111100010110000011111111111001111111111111100000011111111101
1000111111
111000001111111111001001111111100000011111111101100010100111111110010000111111010001111100000011111111110010011111111111000001111111111100000111111111011000111111110100010111111000


五、解决问题
发现了四中出错的原因,看样例倒数第四行,还是没有理解道题目意思

六、最后来看别人的代码
晚上研究吧。

10-03 19:20