循环异或加密器
华为笔试真题 6月12号 非AI方向第一题 100分题型
题目内容
给定一个十六进制密钥 keykeykey 和一个十六进制数据 datadatadata,要求实现循环异或操作:
- 将 keykeykey和 datadatadata的每个十六进制字符转换为 444位二进制数值
- 对datadatadata的每一位与keykeykey 的对应位进行异或操作
- datadatadata和 keykeykey的对齐方式为按照字符顺序从左向右对齐
- 当 keykeykey 的长度小于datadatadata 时,循环使用keykeykey(即 keykeykey 重复拼接至与 datadatadata 等长)
- 可参考样例111中的对齐、keykeykey循环使用以及keykeykey截断方式
输入描述
- 第一行输入为 TTT,1≤T≤2001 \leq T \leq 2001≤T≤200,表示接下来有 T 行,每行一个 keykeykey和 datadatadata,keykeykey 和 datadatadata之间通过空格隔开
- keykeykey 长度至少为111,不超过100001000010000个字符
- datadatadata 长度至少为111,不超过100001000010000个字符
- 字符由数字000$9$,大写字符$A$FFF组成
输出描述
- 输出TTT行,每行对应一个测试用例结果:
- 输出异或后的十六进制大写字符串(长度与datadatadata 相同)
样例1
输入
1
A 1234
输出
B89E
说明
key = "A" → 二进制 1010 data = "1234" → 二进制 0001 0010 0011 0100
循环异或过程: 0001 0010 0011 0100 (data) 1010 1010 1010 1010 (key循环使用)
1011 1000 1001 1110 (异或结果)
B 8 9 E 实际输出应该是 "B89E"
样例2
输入
1
FF A5
输出
5A
说明
key = "FF" → 二进制 1111 1111 data = "A5" → 二进制 1010 0101
1010 0101 1111 1111
0101 1010 → "5A"
样例3
输入
2
AB 12345
FF A5
输出
B99FF
5A
题解和思路
思路
实现思路:模拟
- 预处理,使用哈希表构建
十进制 -> 十六进制字符映射, 十六进制字符 -> 十进制映射 - 求出对应长度
n = key.size(),m = data.size() - 从前往后枚举
data每个字符:- data对应字符为
data[i], key对应字符为key[i % n]通过取余实现循环拼接。 - 接下来就是将对应字符 转换为 十进制,进行异或运算。
- 将异或运算的值转换为十六进制字符加入结果即可
- data对应字符为
C++
cpp
#include<bits/stdc++.h>
using namespace std;
unordered_map<char, int> charToInt;
unordered_map<int, char> intToChar;
// 构建十进制 -> 字符映射, 字符 ->十进制映射
void init() {
for (int i = 0; i < 16; i++) {
char c;
if (i < 10) {
c = '0' + i;
} else {
c = 'A' + (i - 10);
}
charToInt[c] = i;
intToChar[i] = c;
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
init();
int T;
cin >> T;
while (T--) {
string key, data;
cin >> key >> data;
int n = key.size();
int m = data.size();
string ans;
for (int i = 0; i < m; i++) {
char a = data[i];
// 通过取余达到拼接对齐
char b = key[i % n];
char c = intToChar[charToInt[a] ^ charToInt[b]];
ans.push_back(c);
}
cout << ans << endl;
}
return 0;
}
Java
java
import java.io.*;
import java.util.*;
public class Main {
static Map<Character, Integer> charToInt = new HashMap<>();
static Map<Integer, Character> intToChar = new HashMap<>();
// 构建十进制 -> 字符映射,字符 -> 十进制映射
static void init() {
for (int i = 0; i < 16; i++) {
char c;
if (i < 10) {
c = (char) ('0' + i);
} else {
c = (char) ('A' + (i - 10));
}
charToInt.put(c, i);
intToChar.put(i, c);
}
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
init();
int T = Integer.parseInt(br.readLine());
while (T-- > 0) {
StringTokenizer st = new StringTokenizer(br.readLine());
String key = st.nextToken();
String data = st.nextToken();
int n = key.length();
int m = data.length();
StringBuilder ans = new StringBuilder();
for (int i = 0; i < m; i++) {
char a = data.charAt(i);
// 通过取余达到拼接对齐
char b = key.charAt(i % n);
char c = intToChar.get(
charToInt.get(a) ^ charToInt.get(b)
);
ans.append(c);
}
System.out.println(ans);
}
}
}
python
python
import sys
# 构建十进制 -> 字符映射,字符 -> 十进制映射
charToInt = {}
intToChar = {}
for i in range(16):
if i < 10:
c = chr(ord('0') + i)
else:
c = chr(ord('A') + i - 10)
charToInt[c] = i
intToChar[i] = c
input = sys.stdin.readline
T = int(input())
for _ in range(T):
key, data = input().split()
n = len(key)
m = len(data)
ans = []
for i in range(m):
a = data[i]
# 通过取余达到拼接对齐
b = key[i % n]
c = intToChar[charToInt[a] ^ charToInt[b]]
ans.append(c)
print("".join(ans))
Javascript
js
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
rl.on("line", line => {
input.push(line.trim());
});
rl.on("close", () => {
const charToInt = new Map();
const intToChar = new Map();
// 构建十进制 -> 字符映射,字符 -> 十进制映射
for (let i = 0; i < 16; i++) {
let c;
if (i < 10) {
c = String.fromCharCode('0'.charCodeAt(0) + i);
} else {
c = String.fromCharCode('A'.charCodeAt(0) + i - 10);
}
charToInt.set(c, i);
intToChar.set(i, c);
}
let idx = 0;
let T = Number(input[idx++]);
let ans = [];
while (T--) {
let [key, data] = input[idx++].split(" ");
let n = key.length;
let m = data.length;
let cur = [];
for (let i = 0; i < m; i++) {
let a = data[i];
// 通过取余达到拼接对齐
let b = key[i % n];
let c = intToChar.get(
charToInt.get(a) ^ charToInt.get(b)
);
cur.push(c);
}
ans.push(cur.join(""));
}
console.log(ans.join("\n"));
});
Go
go
package main
import (
"bufio"
"fmt"
"os"
)
var charToInt map[byte]int
var intToChar map[int]byte
// 构建十进制 -> 字符映射,字符 -> 十进制映射
func initMap() {
charToInt = make(map[byte]int)
intToChar = make(map[int]byte)
for i := 0; i < 16; i++ {
var c byte
if i < 10 {
c = byte('0' + i)
} else {
c = byte('A' + (i - 10))
}
charToInt[c] = i
intToChar[i] = c
}
}
func main() {
in := bufio.NewReaderSize(os.Stdin, 1<<20)
initMap()
var T int
fmt.Fscan(in, &T)
for ; T > 0; T-- {
var key, data string
fmt.Fscan(in, &key, &data)
n := len(key)
m := len(data)
ans := make([]byte, 0, m)
for i := 0; i < m; i++ {
a := data[i]
// 通过取余达到拼接对齐
b := key[i%n]
c := intToChar[charToInt[a]^charToInt[b]]
ans = append(ans, c)
}
fmt.Println(string(ans))
}
}