链接和思路
OJ链接:传送门。由于题目较长,感兴趣的读者可以自行访问链接查阅,具体细节不在本文重述。
文件压缩涉及到的编解码,贯穿了计算机计算、存储和通信的方方面面。本题要为2MB以内的压缩文件写解码器,给出的需求很明确,不存在太多的复杂度优化的空间,主要的难度是将业务需求仔细实现。由于位操作并非经常涉及,所以可能因大小端问题或粗心而出错。
AC代码
本文提供满分代码。使用CPP14即可编译。
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
vector<unsigned char> bin_code;
string input;
unsigned int cur_idx = 0;
string output;
void print_output() {
for (int i = 0; i < ceil(output.length() / 16.0); i++) {
cout << output.substr(16 * i, 16) << endl;
}
}
void init() {
int s;
cin >> s;
bin_code.resize(s);
for (int i = 0; i < (ceil(s / 8.0)); ++i) {
string line;
cin >> line;
input.append(line);
}
for (int i = 0; i < input.length(); i += 2) {
char tmp[3];
tmp[0] = input[i];
tmp[1] = input[i + 1];
tmp[2] = 0;
unsigned v;
sscanf(tmp, "%x", &v);
bin_code[i / 2] = v;
}
}
void lead_in() {
while (bin_code[cur_idx++] & 0x80);
// cout << cur_idx << endl;
}
void literal_handle() {
// cout << "start literal handle: cur_idx is " << cur_idx << endl;
unsigned l = bin_code[cur_idx++] >> 2;
if (l < 60) {
l++;
} else {
int tmp = (int) l - 59;
l = 0;
for (int i = 0; i < tmp; i++) {
l = l | (bin_code[cur_idx++] << (8 * i));
}
l++;
}
output.append(input.substr(cur_idx * 2, l * 2));
cur_idx += l;
// print_output();
// cout << "---------" << endl;
// cout << "end literal handle: cur_idx is " << cur_idx << endl;
}
void recall_handle() {
unsigned type = bin_code[cur_idx] & 0x3;
// cout << "start recall handle, type: " << type << endl;
unsigned l = 0, o = 0;
if (0x1 == type) {
l = ((bin_code[cur_idx] >> 2) & 0x7) + 4;
o = bin_code[cur_idx] & 0xe0;
o = o << 3;
o |= bin_code[++cur_idx];
} else {
l = (bin_code[cur_idx] >> 2) + 1;
o |= bin_code[++cur_idx];
o |= (bin_code[++cur_idx] << 8);
}
unsigned cur_len = output.length();
for (unsigned i = cur_len - o * 2; l--;) {
output.push_back(output[i]);
output.push_back(output[i + 1]);
i = i + 2;
if (i == cur_len)
i = cur_len - o * 2;
}
cur_idx++;
// print_output();
// cout << "---------" << endl;
}
void decode_data() {
while (cur_idx < bin_code.size()) {
unsigned type = bin_code[cur_idx] & 0x3;
switch (type) {
case 0x0:
literal_handle();
break;
case 0x1:
case 0x2:
recall_handle();
break;
default:
cout << "?????";
exit(EXIT_FAILURE);
break;
}
}
}
int main() {
init();
lead_in();
decode_data();
print_output();
}