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
五、解決問題 發現了四中出錯的原因,看樣例倒數第四行,還是沒有理解道題目意思
六、最後來看別人的程式碼 晚上研究吧。