乐趣区

头条笔试题-秘密通信解析伪

前几天听一个学长描述了一下他做的几道头条笔试题,自己空闲时间选了一道简单的尝试做了做,由于没有经过校验,答案能对多少,自己也没数,因此读者就当看个乐子,答案是当不得真的。

题目描述

两个人通过加密通信的方式进行通信,每条信息都被编译成二进制数 B(明文),其长度为 N。信息被写下 K 次,每次向右移动 0,1,……,k- 1 位。

例如

B=1001010, K=4
1001010
  1001010
    1001010
      1001010

然后对每一列进行异或操作,结果称为 S(密文)
上面的结果就为

1110100110

要求是写一个程序去实现这种编码的解密过程

输入

第一行两个整数 N 和 K
第二行一个二进制字符串 S,长度为 N +K-1

输出

输出明文 B

解题思路

首先要明白异或运算是干嘛的

异或运算:两个数相等就置 0,不等就置 1。
所以可以看成参与运算的 1 的数量是单数还是偶数

再次可以知道 B 的长度为 N

然后很明显 B 的第一位和最后一位就等于 S 的第一位和最后一位。

private static byte[] decrypt(int N, int K, byte[] S) {byte[] answer = new byte[N];      
        answer[0] = S[0];
        answer[N - 1] = S[S.length - 1]; 
}

可以看出 计算部分要分为两种情况,计算第i 位答案时:

如果 i < k 就需要和前面k - i 个答案进行运算
如果 i >= k 就需要和前面k 个答案进行运算

解码的完整代码如下

    private static byte[] decrypt(int N, int K, byte[] S) {byte[] answer = new byte[N];
        answer[0] = S[0];
        answer[N - 1] = S[S.length - 1];

        for (int i = 1; i < N - 1; i++) {
            int count = 0;

            int temp;   // 用于存储循环次数

            if (i < K) {
                temp = K - i;
                // 前 K 个结束
            } else {temp = K;}

            for (int j = 0; j < temp; j++) {if (answer[j] == 1)
                    count++;
            }

            if (count % 2 == 1) {if (S[i] == 1) {answer[i] = 1;
                } else {answer[i] = 0;
                }
            } else {if (S[i] == 1) {answer[i] = 0;
                } else {answer[i] = 1;
                }
            }
        }

        return answer;
    }
退出移动版