CCF CSP题解:解压缩(202305-3)

链接和思路

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();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曹无悔

请支持我的梦想!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值