|
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
public class UserSolution { private static final int FRAMESIZE = 256; private static int num; private static int max; private static char[][] frames; private static int[] lookingTable; public void Init(int N, int[] size, char[] data, int M, Solution.Huffman[] code) { frames = new char[N][FRAMESIZE]; max = N; int len = 0; for (int i = 0; i < M; i++) if (code[i].codewordLength > len) len = code[i].codewordLength; int mask = 0xFFFFFF >> (24 - len); //用于后面更新tmpCode lookingTable = new int[1 << len]; //查找表,存储tmpCode对应的code数组索引 for (int i = 0; i < M; i++) for (int j = 0; j < 1 << (len - code[i].codewordLength); j++) //长度为codewordLength的code,需要初始化2^(len-code[i].codewordLength)个位置 lookingTable[code[i].codeword << (len - code[i].codewordLength) | j] = i; int baseIdx = 0; for (int i = 0; i < N/16; i++) { int bitIdx = 0; int frameCharIdx = 0; int codeLen = 0; int tmpCode = 0; while (frameCharIdx < 4096) { if (bitIdx == 32768) { //由于使用固定长度的tmpCode,因此需要处理最后bit的边界情况 tmpCode = tmpCode << (len - codeLen); codeLen = len; } while (codeLen < len) { //每次读入len位数据,判断其对应的code int diff = len - codeLen; if (8 - bitIdx%8 >= diff) { //当前data剩余位数足够 tmpCode = tmpCode << diff | (data[baseIdx + (bitIdx>>3)] << (bitIdx%8) >> (8 - diff)); //取对应位,更新tmpCode bitIdx += diff; codeLen = len; } else { //当前data剩余位数不够 int rest = 8 - bitIdx%8; tmpCode = tmpCode << rest | (data[baseIdx + (bitIdx>>3)] & 0xFF >> (bitIdx%8)); //取对应位,更新tmpCode bitIdx += rest; codeLen += rest; } } //此时tmpCode必然对应一个明文,更新到frames中 frames[(i<<4) + frameCharIdx/FRAMESIZE][frameCharIdx%FRAMESIZE] = (char)code[lookingTable[tmpCode]].symbol; frameCharIdx++; codeLen -= code[lookingTable[tmpCode]].codewordLength; //减去上一个char对应的有效位数 tmpCode = tmpCode & (mask >> code[lookingTable[tmpCode]].codewordLength); //去除上一个char对应的有效位后,剩余的tmpCode } baseIdx += size[i]; } //从D frames反推O frames,注意每16个frame为一个block for (int i = 0; i < N/16; i++) for (int k = 1; k < 16; k++) for (int j = 0; j < FRAMESIZE; j++) frames[(i<<4) + k][j] = (char)(frames[(i<<4) + k][j] + frames[(i<<4) + k - 1][j] - 128); } public void Goto(int frame) { num = frame; } public int Tick(char[] screen) { if (num < max) num++; for (int i = 0; i < FRAMESIZE; i++) screen[i] = frames[num - 1][i]; return num - 1; }} |