1. 程式人生 > >Message Decoding

Message Decoding

一、題目大意: 編寫一個解碼程式,對字串進行解碼 解碼規則,根據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


五、解決問題 發現了四中出錯的原因,看樣例倒數第四行,還是沒有理解道題目意思

六、最後來看別人的程式碼 晚上研究吧。