字节跳动 2020年笔试题-秘密通信

问题描述:

小明和安琪是好朋友。最近,他们的谈话被一家侦探机构监控,所以他们想将他们的谈话内容进行加密处理。
于是,他们发明了一种新的加密方式。每条信息都被编译成二进制数B(明文),其长度为N。
然后该信息被写下K次,每次向右移动0,1,…,K-1位。
例如:B = 1001010,K=4
1001010
1001010
1001010
1001010
然后对每一列进行异或操作,并且把最终所得的结果记录下来,我们将该数称为S(密文)。
例如上述例子的结果为:1110100110。
最后,将编码的信息S和K发送给安琪。
小明已经实现了这种编码的加密过程,但他要求安琪写一个程序去实现这种编码的解密过程,你能帮助安琪实现解密过程吗?

输入格式:

第一行输入两个整数 NK

第二行输入一个二进制字符串S,长度是N + K - 1

输出格式:

输出明文B

数据范围

1<=N<=10^6
1<=K<=10^6

思路:

首先,通过给出的示例,分析压缩的规律,从压缩的规律中反推出解压的算法。
首先分析压缩的过程:

0 = 0
1 = 1 ^ 0
1 = 0 ^ 1 ^ 0
0 = 0 ^ 1 ^ 0 ^ 1
0 = 1 ^ 0 ^ 1 ^ 0
1 = 0 ^ 1 ^ 0 ^ 0
0 = 1 ^ 0 ^ 0 ^ 1
1 = 0 ^ 0 ^ 1
1 = 0 ^ 1
1 = 1

将要求解的明文串设定为:abcdefg
将压缩后的密文串设定为:hijklmnopq
从新分析压缩过程可得到如下:

q = g
p = f ^ g
o = e ^ f ^ g
n = d ^ e ^ f ^g
m = c ^ d ^ e ^ f
l = b ^ c ^ d ^ e
k = a ^ b ^ c ^ d
j =     a ^ b ^ c
h =         a

将公式a ^ b = c ⇒ a = b ^ c代入,可推断出:

g = q

f = g ^ p = p ^ q
e = o ^ f ^ g = o ^ p ^ q ^ q = o ^ p
d = n ^ e ^ f ^ g = ...    = n ^o

c = m ^ d ^ e ^ f = m ^ n ^ o ^ o ^ p ^ p ^ q = m ^ n ^ q
b = l ^ c ^ d ^ e = l ^ m ^ p
a = k ^ b ^ d ^ d   = k ^ l ^ o

可以推断出规律:

  • 0 : res[0] = S[0]
  • 1 ~ K-1 : res[i] = S[i] + S[i-1]
  • K ~ N res[i] = S[i] + S[i-1] + res[i-k+1]

完整代码:

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int N =in.nextInt() , K = in.nextInt();
        String S = in.next();
        int S1[] = new int[N+K-1];
        int res[] = new int[N];
        for (int i = 0;i < S.length(); i++) {
            S1[i] = S.charAt(i)  - '0';
        }
        res[0] = S1[0];
        for (int i = 1;i < K; i++) {
            res[i] = S1[i] ^ S1[i-1];
        }
        for (int i = K;i < N; i++) {
            res[i] = S1[i] ^ res[i-K] ^ S1[i-1];
        }
        for (int i = 0;i < res.length; i++) {
            System.out.println(res[i]);
        }
    }
}

附加GitHub链接

发布了11 篇原创文章 · 获赞 15 · 访问量 916

猜你喜欢

转载自blog.csdn.net/qq_36008321/article/details/104410190