2023–05-3 解压缩 大模拟(没有特殊算法)
2023–05-3 解压缩 大模拟(没有特殊算法)
这题实际并不难,主要是要注意一些细节,比较考验你的编程习惯和逻辑是否清晰
思路就是按题目的来模拟
题目其实并不难理解,就是先算引导区、再算数据区的数据
遇到的问题(解题过程)
- 第一个遇到的问题就是输出没有搞对
每行8个字节16个字符换一次行
for (int i = 0; i < allData.size(); i++) { if (i != 0 && i % 16 == 0) { cout << endl; } cout << allData[i]; }
然后从0分变成了40分
- 没有想清楚pos的含义和字节的关系
就是这里应该对16取余但是对8取的余,并且重写了这块也就是对位运算转化为了十进制运算,逻辑更加清晰了,并且补充了对回溯引用的代码,然后就变成了60分,
else if (t % 4 == 2) { l = t / 4 + 1; // 往后读取两个字节作为o o = hexToDec(string(temp[pos / 16].begin() + pos % 16, temp[pos / 16].begin() + pos % 16 + 2)); pos += 2; o += hexToDec(string(temp[pos / 16].begin() + pos % 16, temp[pos / 16].begin() + pos % 16 + 2)) * 256; pos += 2; }
- 最坑的一个点就是对引导区长度计算的错误
本来是使用按位计算的
没有理清楚,并且不知道位运算的优先级是最低的(除去三元运算)详情请看c++运算优先级
用的是
if(num & 128 !=1)
这样不对这样num&128!=128才对
因为
1000 0000&1000 0000 = 1000 0000
只有第一位是1时4才是1000 0000 也就是128
然后使用了十进制这样更清晰一点
if(num<128)
然后就直接100分了
完整代码
#include <bits/stdc++.h>
using namespace std;
int s;
string temp[5000000];
int pos = 0;
string allData = "";
int hexToDec(string a) // 十六进制转十进制
{
int num = 0;
for (int i = 0; i < a.size(); i++)
{
int t;
if (a[i] >= '0' && a[i] <= '9')
{
t = a[i] - '0';
}
else
t = a[i] - 'a' + 10;
num *= 16;
num += t;
}
return num;
}
void addToData(int len) // 把压缩的数据插入到解压缩数据中
{
len = len * 2;
int end = pos + len;
for (; pos < end; pos++)
{
allData.push_back(temp[pos / 16][pos % 16]);
}
}
int main()
{
cin >> s;
getchar();
int end = s / 8;
if (s % 8 == 0)
end--;
for (int i = 0; i <= end; i++)
{
getline(cin, temp[i]);
}
int len = 0;
int base = 1;
for (int i = 0; i < 4; i++)
{
int num = hexToDec(string(temp[0].begin() + i * 2, temp[0].begin() + i * 2 + 2));
len += base * (num % 128);
base *= 128;
pos += 2;
if (num<128)
{
break;
}
}
while (pos < s * 2)
{
// 字符串切片操作
string type = string(temp[pos / 16].begin() + pos % 16, temp[pos / 16].begin() + pos % 16 + 2);
pos += 2;
int t = hexToDec(type);
if (t % 4 == 3) // 不合法
{
break;
}
else if (t % 4 == 0) // 字面量
{
int length = t / 4;
if (length < 60)
{
addToData(length + 1);
}
else
{
string l = "";
for (int i = length - 59 - 1; i >= 0; i--)
{
l.push_back(temp[(pos + i * 2) / 16][(pos + i * 2) % 16]);
l.push_back(temp[(pos + i * 2 + 1) / 16][(pos + i * 2 + 1) % 16]);
}
pos += (length - 59) * 2;
length = hexToDec(l); // 将十六进制字符串转化为十进制
addToData(length + 1); // 插入到解压缩数据中
}
}
else // 回溯索引
{
int o, l;
if (t % 4 == 1)
{
// 高三位和后一个字节
o = (t / 32) * 256 + hexToDec(string(temp[pos / 16].begin() + pos % 16, temp[pos / 16].begin() + pos % 16 + 2));
pos += 2;
l = (t / 4) % 8 + 4; // 中间三位 再加4
}
else if (t % 4 == 2)
{
l = t / 4 + 1;
// 往后读取两个字节作为o
o = hexToDec(string(temp[pos / 16].begin() + pos % 16, temp[pos / 16].begin() + pos % 16 + 2));
pos += 2;
o += hexToDec(string(temp[pos / 16].begin() + pos % 16, temp[pos / 16].begin() + pos % 16 + 2)) * 256;
pos += 2;
}
// 得到o和l之后添加到解压缩数据中
if (o >= l)
{
allData += string(allData.end() - o * 2, allData.end() - o * 2 + l * 2);
}
else if (o < l)
{
string t1 = string(allData.end() - o * 2, allData.end());
for (int i = 0; i < l * 2; i++)
{
allData.push_back(t1[i % t1.size()]);
}
}
}
}
for (int i = 0; i < allData.size(); i++)
{
if (i != 0 && i % 16 == 0)
{
cout << endl;
}
cout << allData[i];
}
return 0;
}