一、题目
题目链接:ccf官网
二、题解(Java版)
目前只能拿到八十分,不知道哪里扣掉了分,(有大佬知道的话可以在评论区留言),而且使用了快速输入和输出(经测试可以多得十分)。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
public class Main {
static int index = 0;
static StringBuffer str = new StringBuffer(); // 存储输入的所有数据
// 得到某个字节转换成的八位二进制字符串
static String getBinaryString(String twoBit) {
// 先十六进制转十进制,再十进制转二进制
String binary = Integer.toString(Integer.parseInt(twoBit, 16), 2);
return String.format("%8s", binary).replace(' ', '0'); // 不够八位的话默认不会在前面补齐0,所以改成这样
}
// 将二进制的高六位转化为十进制数字
static int tranferHigh6BitToInteger(char[] bit) {
return Integer.parseInt(String.valueOf(bit).substring(0, 6), 2);
}
// 将二进制的倒数第2~4位转化为十进制数字
static int tranfer24BitToInteger(char[] bit) {
return Integer.parseInt(String.valueOf(bit).substring(3, 6), 2);
}
// 读入num个字节,即2*num位数据
static String readBytes(int num) {
String temp = str.substring(index, index + (num *2));
index += (num *2); // 索引后移
return temp;
}
public static void main(String[] args) throws IOException {
BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
StringBuilder result = new StringBuilder(); // 存储解压缩后的结果
int s = Integer.parseInt(buf.readLine());
if (s % 10 != 0)
s += 8;
for (int i = 0; i < s / 8; i++) {
String temp = buf.readLine();
str.append(temp);
}
// StringBuffer guide = new StringBuffer(); // 存储引导区字符串
String guidePart = readBytes(1); // 引导区的两个字节
// guide.append(guidePart);
char highBit = getBinaryString(guidePart).charAt(0); // 最高位
while (highBit != '0') {
guidePart = readBytes(1);
// guide.append(guidePart);
highBit = getBinaryString(guidePart).charAt(0);
}
// 由引导区计算原始数据长度,可以测试得到的结果长度对不对,这里我就先不写了
// ……
while (index != str.length()) {
String dataPart = readBytes(1);
char[] dataPartCharArray = getBinaryString(dataPart).toCharArray();
if (dataPartCharArray[6] == '0' && dataPartCharArray[7] == '0') { // 字面量
int L = tranferHigh6BitToInteger(dataPartCharArray);
if (L < 60) {
result.append(readBytes(L + 1));
} else { // 字面量的第二种情况
L -= 59;
String zimianliang2 = "";
while (L-- > 0) {
zimianliang2 = readBytes(1) + zimianliang2; // 小端序
}
int zimianliang2DataLong = Integer.parseInt(zimianliang2, 16);
zimianliang2DataLong++;
result.append(readBytes(zimianliang2DataLong));
}
} else if (dataPartCharArray[6] == '1' && dataPartCharArray[7] == '0') { // 回溯引用
int L = tranferHigh6BitToInteger(dataPartCharArray);
L++;
String bigBit = readBytes(1);
String smallBit = readBytes(1);
int offset = Integer.parseInt(smallBit + bigBit, 16);
if (offset >= L) {
String back = result.substring(result.length() - offset * 2, result.length() - offset * 2 + L * 2); // offset的单位是字节,所以要*2
result.append(back);
} else {
int n = L / offset; // 除数
int m = L % offset; // 余数
String back = result.substring(result.length() - offset * 2, result.length());
while (n-- > 0) {
result.append(back);
}
result.append(result.toString().substring(result.length() - offset * 2, result.length() - offset * 2 + m * 2));
}
} else { // 最低位为01
int L = tranfer24BitToInteger(dataPartCharArray);
L += 4;
String pre = String.valueOf(dataPartCharArray).substring(0, 3);
String post = getBinaryString(readBytes(1));
int offset = Integer.parseInt(pre + post, 2);
if (offset >= L) {
String back = result.substring(result.length() - offset * 2, result.length() - offset * 2 + L * 2); // offset的单位是字节,所以要*2;-6即减去前面的c60300
result.append(back);
} else {
int n = L / offset; // 除数
int m = L % offset; // 余数
String back = result.substring(result.length() - offset * 2, result.length());
while (n-- > 0) {
result.append(back);
}
result.append(result.toString().substring(result.length() - offset * 2, result.length() - offset * 2 + m * 2)); // +2即加上最后一个字节
}
}
}
for (int i = 0; i < result.length(); i++) {
out.print(result.charAt(i));
if ((i + 1) % 16 == 0) {
out.println();
}
}
out.flush();
out.close();
}
}