CSP-202305-3 解压缩(decompress)

【ccf-csp题解】第30次csp认证-第三题-解压缩-字符串模拟 本文章包含第30次csp认证第三题的满分代码 阅读详情

不枉我给C++作业出过十六进制转换、字节解析、字节序、位模式等题目,这次擦边。
二进制解析难测难调,但题目“输入数据保证是合法的”就很客气,而且CSP不罚时,可以放心用断言验证条件。

实现的技巧:

  • 函数式风格,短函数实现,使其功能单一,易于测试。
  • 把参数解析和数据解压分开,简化函数。
  • 用断言把样例都做成单元测试,这样实现出来就是正确的,不用调试。
#include <bits/stdc++.h>
using namespace std;

using ub_t = unsigned char;     // 无符号字节类型
using cp_t = const ub_t*;       // 常性字节指针
using cc_t = const ub_t* const; // 常性字节指针常量

constexpr int hex_value(char c) { // 十六进制数字转值
  return (c >= '0' && c <= '9') ? (c - '0') : (c - 'a' + 10);
}

constexpr ub_t parse_byte(char h, char l) {  // 拼装字节
  return (hex_value(h) << 4) | hex_value(l); // 1-hex ~ 4-bit
}

// 从ist读取n字节十六进制数(2*n个字符)存到pd缓冲区,返回数据结束位置。
ub_t* read_bytes(ub_t* pd, cc_t pe, istream& ist, const int n) {
  assert(pd + n <= pe);
  char h, l; // 十六进制高、低半字节
  for(int i = 0; i < n && ist >> h >> l; ++i) {
    *pd++ = parse_byte(h, l); // 及时递增
  }
  assert(ist); // 不应EOF
  return pd;
}

// 解析导引域,获取原始数据长度,返回未解字节位置
cp_t raw_length(cp_t ps, cc_t pe, int& g) {
  g = 0;
  int r = 1;
  do {
    assert(ps < pe);
    g += (*ps & 0x7F) * r; // 低7位是值,相当于128进制。
    r *= 128;
  } while(*ps++ & 0x80); // 长度末字节最高位是0
  return ps;
}

// 解析字面量元素的长度,返回未解字节位置
cp_t literal_length(cp_t ps, cc_t pe, int& l) {
  assert(ps < pe);
  ub_t b = *ps++;
  b >>= 2;
  if(b < 60) { // l <= 60时
    l = b + 1; // 第一个字节的高6位表示(l − 1)
  } else {
    b -= 59; // 60~63分别表示后续有1~4字节长度
    assert(ps + b <= pe);
    l = 0;
    for(int r = 1; b > 0; --b, ++ps) {
      l += *ps * r;
      r *= 256;
    }
    ++l;
  }
  return ps;
}

// 从(p-o)处反复提取直到l字节,填充到p处,返回数据结束位置。
ub_t* extract(ub_t* p, cc_t pe, int o, int l) {
  assert(p + l <= pe);           // 缓冲区够大
  for(cc_t pb = p - o; l > 0;) { // 起始位置pb不变
    const int d = min(o, l);
    memcpy(p, pb, d);
    p += d;
    l -= d;
  }
  return p;
}

cp_t back_ref_1(cp_t ps, cc_t pe, int& o, int& l) {
  assert(ps + 2 <= pe);
  l = ((*ps & 0b00011100) >> 2) + 4;
  o = ((*ps & 0b11100000) << 3) | ps[1];
  assert(l >= 4 && l <= 11);
  assert(o >= 1 && o <= 2047);
  return ps + 2;
}

cp_t back_ref_2(cp_t ps, cc_t pe, int& o, int& l) {
  assert(ps + 3 <= pe);
  l = (*ps >> 2) + 1;
  o = (ps[2] * 256) + ps[1];
  assert(l >= 1 && l <= 64);
  assert(o >= 1 && o <= 65535);
  return ps + 3;
}

ub_t* decompress(ub_t* pd, cc_t de, cp_t ps, cc_t pe) {
  for(int o, l; ps < pe;) {
    switch(*ps & 3) { // 每个元素的第一个字节的最低两位表示了元素的类型。
    case 0: // 当最低两位为 0 时,表示这是一个字面量
      ps = literal_length(ps, pe, l);
      assert(l >= 1);
      assert(ps + l <= pe);
      assert(pd + l <= de);
      memcpy(pd, ps, l); // 字面量包含一些字节,解压时直接将其输出即可。
      ps += l;
      pd += l;
      break;
    case 1: // 回溯引用1型
      ps = back_ref_1(ps, pe, o, l);
      pd = extract(pd, de, o, l);
      break;
    case 2: // 回溯引用2型
      ps = back_ref_2(ps, pe, o, l);
      pd = extract(pd, de, o, l);
      break;
    default:         // 元素的首字节的最低两位不允许是11
      assert(false); // 输入数据保证是合法的
    }
  }
  return pd;
}

void print(cp_t ps, cc_t pe, const char hex_digits[16]) {
  for(int i = 0; ps != pe; ++ps, ++i) {
    cout << hex_digits[*ps >> 4] << hex_digits[*ps & 0xF];
    if((i % 8) == 7) {
      cout << '\n';
    }
  }
}

void test(const char hex_digits[16]) {
#ifndef ONLINE_JUDGE
  {
    assert(hex_value('0') == 0);
    assert(hex_value('9') == 9);
    assert(hex_value('a') == 10);
    assert(hex_value('f') == 15);
  }
  {
    assert(parse_byte('0', '0') == 0x00U);
    assert(parse_byte('0', '8') == 0x08U);
    assert(parse_byte('8', '0') == 0x80U);
    assert(parse_byte('f', 'f') == 0xffU);
  }
  {
    istringstream iss(hex_digits);
    ub_t buf[10];
    cp_t pt = read_bytes(buf, buf + sizeof(buf), iss, 8);
    assert(pt == buf + 8);
    assert(buf[0] == 0x01);
    assert(buf[1] == 0x23);
    assert(buf[2] == 0x45);
    assert(buf[3] == 0x67);
    assert(buf[4] == 0x89);
    assert(buf[5] == 0xAB);
    assert(buf[6] == 0xCD);
    assert(buf[7] == 0xEF);
  }
  {
    int g = -1;
    const ub_t s1[] = "\xAC\x0A";
    auto pt = raw_length(s1, s1 + sizeof(s1), g);
    assert(pt = s1 + 2);
    assert(g == 1324);
  }
  {
    int l;
    const ub_t s[] = "\xE8";
    auto pt = literal_length(s, s + sizeof(s), l);
    assert(pt == s + 1);
    assert(l == 58 + 1);
  }
  {
    int l;
    const ub_t s[] = "\xF4\x01\x0A";
    auto pt = literal_length(s, s + sizeof(s), l);
    assert(pt == s + 3);
    assert(l == (0x0A01 + 1));
  }
  {
    int o, l;
    const ub_t s[] = "\x2D\x1A";
    auto pt = back_ref_1(s, s + sizeof(s), o, l);
    assert(pt = s + 2);
    assert(o == 282);
    assert(l == 7);
  }
  {
    int o, l;
    const ub_t s[] = "\x3E\x1A\x01";
    auto pt = back_ref_2(s, s + sizeof(s), o, l);
    assert(pt = s + 3);
    assert(o == 282);
    assert(l == 16);
  }
#endif
}

const char hex_digits[] = "0123456789abcdef";
constexpr int N = 1024 * 1024 * 3;
ub_t vs[N], vd[N]; // 源(src)、目的(dst)数据

int main() {
  ios::sync_with_stdio(false); // IO多达几十万项,要优化
  cin.tie(0);
  cout.tie(0);
  test(hex_digits);
  int s = 1e9, d = 1e9; // 源数据字节数、解压数据字节数
  cin >> s >> ws;
  assert(s <= N); // 源缓冲区够大
  cc_t se = read_bytes(vs, vs + N, cin, s);
  assert(se == vs + s);
  cc_t ps = raw_length(vs, se, d);
  assert(d <= N); // 源缓冲区够大
  cc_t de = decompress(vd, vd + d, ps, se);
  assert(de == vd + d);
  print(vd, de, hex_digits);
  return 0;
}
python 爬虫 xpath 存储到数据库 参考 阅读详情

相关推荐

【SimPy系列博客之官方example学习与解读】—— Example 1: Bank Renege

Hello,优快云的各位小伙伴们,拖更了几年后,又重新开始记录这段时间准备学习的东西啦!最近博主在学习 SimPy 的相关知识,发现国内关于 SimPy 的介绍还是相对较少,且缺乏系统性,因此博主打算用1~2周的时间,边学边记,打算从 SimPy 官方给出的几个例子出发分析 SimPy 的使用场景和用法,希望能和大家互勉!那废话不多说,我们直接开始吧!今天要学习的例程是 Bank Renege。

凝望,划过星空的博客 2008

CCF-CSP真题《202305-3 解压缩》思路+python,c++满分题解

本文为大家用c++题解了CCF-CSP真题《202305-3 解压缩》,希望对你有帮助~~

weixin_53919192的博客 1万+

从SolidWorks到URDF:插件使用、关节配置与PyBullet仿真避坑指南

本文提供了一份从SolidWorks导出URDF模型并导入PyBullet进行仿真的完整实战指南。详细讲解了SolidWorks插件的正确安装与配置、关节类型的选择与坐标系对齐的核心技巧,并针对PyBullet仿真中常见的模型散架、路径错误、物理属性异常等问题提供了深度避坑解决方案,帮助机器人开发者高效完成从设计到仿真的全流程。

weixin_29081101的博客 542

CCF-CSP认证202305-3:解压缩(AC代码+超详细解析)

存储读取到的字节和对应的整数state记录当前的状态:“guide”意为接下来读的字节属于导引域;“finish”意为告一段落,该读入新的数据域了;意为接下来读的字节属于字面量的说明部分;意为接下来读的字节属于回溯引用说明部分中的形式1;意为接下来读的字节属于回溯引用说明部分中的形式2记录导引域的字节数;记录从导引域解析出来的原始数据的长度const_l记录接下来的字面量的字节数;当l>60时,记录接下来有几个字节算作字面量的说明部分,记录已经读了几个字节的字面量的说明部分var_o。

uvsuhs的博客 2050

数据分析:美团大赛的具体案例制作

在数据集中,存在三个变量的经纬度数据,分别是商家的经纬度数据('sender_lng', 'sender_lat'),顾客的经纬度数据('recipient_lng', 'recipient_lat')和骑手的经纬度数据('grab_lng', 'grab_lat')。根据结果可知,平台订单创建时间的中位数为2022-10-21 02:59:01,平台订单创建时间的众数为2022-10-19 03:29:41、2022-10-23 03:29:47,与直方图相符。接下来,我们对是否为预定订单变量进行分析。

m0_68269346的博客 2495

(头歌作业)—6.1 葡萄酒评论分析报告(project)

请读取文件中的数据,完成以下任务:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬。请读取文件中的数据,完成以下任务:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬。请读取文件中的数据,完成以下任务:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬。

2301_80677920的博客 1244

CSPCCF认证202305-3解压缩 解析(不需要算法)

最近准备参加csp认证,做了几套题,放假闲的无聊写一下解析。 一般csp认证的第三道大题都是小模拟,主要考验我们做题者的阅读能力(最重要的!!!)以及敲代码的熟练程度,基本不会涉及到算法,适合我这种不会算法的小弱鸡。

weixin_66586476的博客 1169

在ARM平台上使用Anbox和LXC进行ARM开发调试

在ARM平台上使用Anbox和LXC进行ARM开发调试是一种强大的工具组合。通过安装和配置Anbox和LXC,以及在LXC容器中运行ARM应用程序,开发人员可以方便地进行ARM开发和调试。LXC(Linux容器)是一种轻量级虚拟化技术,它提供了一种在单个主机上运行多个独立的Linux容器的方法。我们将讨论安装和配置Anbox和LXC,以及如何在容器中运行ARM应用程序。通过上述步骤,你现在可以在LXC容器中运行ARM应用程序,并使用Anbox在ARM平台上进行开发和调试。步骤2:启动LXC容器。

KwmGroovy的博客 735

CSP202305-3-解压缩

只有十分,未来考虑再改。

qq_35838922的博客 159

实用指南:制作通用的INCA和CANape兼容A2L文件

A2L(ASAM MCD-2 Measurement and Calibration Data)文件是描述ECU(电子控制单元)测量和校准数据的标准文件格式。在标定工作中,A2L文件扮演着极为重要的角色,它定义了测量通道、校准参数等关键信息,为工程师提供了统一的描述方式。INCA和CANape是两种常见的汽车电子系统标定工具,分别由ETAS和Vector公司开发。它们在汽车电子系统的开发和调试过程中发挥着重要作用,提供了丰富的标定功能和用户友好的界面。

一直在水些技术小文 2922

锂电池寿命预测 | Pytorch实现基于Transformer 的锂电池寿命预测(NASA数据集)

锂电池寿命预测 | Pytorch实现基于Transformer 的锂电池寿命预测(NASA数据集)

算法如诗的博客 5584

CSP-2023-05-3(解压缩)

CSP-2023-05-3(解压缩)

wyb23187的博客 357

2024年数字IC秋招-格科微-数字电路设计工程师-笔试题

笔试题型:简答题(9个)笔试平台:牛客(电脑监控)笔试时间:2h。

qq_42135020的博客 1605

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

CCF CSP考试题《解压缩》的满分题解。

曹无悔的博客 837

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

CCF-CSP 30次 第三题【解压缩】(stoi进制转换+bitset)

太复杂了,还没完全弄明白。

QZZ_PP的博客 569

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

CCF-CSP认证考试 202305-3 解压缩 100分题解

字符串处理、位运算

Pujx的博客 1764

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

CSP-解压缩 C/C++满分题解

需要注意有些数据是小端存储,需要转换一下。大模拟,按照题意一步步写即可。

qq_33685264的博客 404

CSP 202305-3 解压缩

这道T3主要是能够读懂题目,然后根据题意进行模拟,需要比较多的位运算,在此题,我选择用uint8_t存储一个字节,然后对字符和数字进行了转换。

weixin_44340652的博客 219

CSP 202305-3 解压缩 100分

CSP解压缩满分题解

m0_55964465的博客 331

【CCF-CSP】202305-3解压缩

模拟、文本处理

whaoe_m的博客 1148

第30次csp认证——前三题个人题解思路与反思

第30次ccf-csp认证,重复局面,矩阵运算,解压缩,前三题的题解以及个人思路

qq_57708664的博客 5149

CCF CSP 2016年12月第4题 压缩编码(区间DP)

问题描述 试题编号: 201612-4 试题名称: 压缩编码 时间限制: 3.0s 内存限制: 256.0MB 问题描述: 问题描述   给定一段文字,已知单词a1, a2, …, an出现的频率分别t1, t2, …, tn。可以用01串给这些单词编码,即将每个单词与一个01串对

nudt_oys的博客 1264

CCF-CSP真题《202305-1 重复局面》思路+python,c++,Java满分题解

本文为大家用python,c++题解CCF-CSP真题《202305-1 重复局面》并提供一点小思路。

weixin_53919192的博客 2万+

第三十次csp认证 202305-2 矩阵运算(纯记录)

矩阵连乘,但是只乘3次,无需动态规划。根据题意d数值远小于n,先做矩阵Q乘K再乘V需要做n*d*n+n*n*d次乘法,循环次数太多,会超时。先做矩阵K乘V再乘Q需要做d*n*d+n*d*d次乘法,循环次数大大减少。根据提示,计算结果太大,需要用到long long型。(纯记录向,在校生写给自己看,代码很烂)

qq_57295233的博客 3591

CSP 202305-2 矩阵运算 C/C++满分题解

3.计算完直接输出,避免再用一个很大的数组去存,节约时间空间。1.数据很大,要用long long定义,否则数据会爆。2.矩阵相乘要调换顺序。

小瑾的博客 851

求助 CSP202305-3 解压缩 运行错误 50分

求助 CSP202305-3 解压缩 运行错误 50分

xblyxjj的博客 563
上一篇: CSP-202303-3 LDAP
CodeArhat
博客等级 码龄15年 13粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值