CCF解压缩 Java题解

6 篇文章 0 订阅

一、题目

题目链接: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();
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

飞影铠甲

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值