1.题意:(题意巨巨巨巨巨长)
给出一串16进制的字符串,把他转化为二进制。然后给你一些二进制串 si 对应的字符ACII码 ci (每个si串前缀不同),然后给你对于转化为二进制后的字符串的算法规则:
八个字符为一个部分,第九个字符时有两种情况:
(1)若前八个字符内含有奇数个1且第九个字符为0 或者 前八个字符内含有偶数个1且第九个字符为1 则保留前八位
(2)否则这九位全部舍弃
然后对于处理好的最终字符串,把他按照si跟ci的对应规则转化为相应字符输出,注意:这里限定输出n个字符,多于不输出(坑点)
2.分析:
预处理16进制到二进制,处理保留字符串,把对应规则保存到字典树。输出最终字符串时跑一下字典数即可。
3.代码:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 1;
char chara[] = "0123456789ABCDEF";//编号对应16进制单位
char hexd[][10] = {"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"};//预处理每个16进制对应四位二进制
int rela[100];
struct Node{
int next[2];
bool judge;
int sign;
}node[maxn*4];
char ans[4*maxn];
char sum[4*maxn];
char compare[maxn];
int n,m,tot,mm;
void init(){
for(int i = 0;i<16;i++){//初始化16进制每个单位对应编号
int j = chara[i] - '0';
rela[j] = i;
}
}
int CreatTree(){//添加节点
node[tot].next[0] = node[tot].next[1] = -1;
node[tot].judge = false;
node[tot].sign = 0;
return tot++;
}
void InsertTree(int a,char*s){//插入
int index = 0;
int l = strlen(s);//这里一定先求出strlen,不要用for(int i = 0;i<strlen(s);i++)超时。。
for(int i = 0;i<l;i++){
int j = s[i] - '0';
if(node[index].next[j]==-1){
node[index].next[j] = CreatTree();
}
index = node[index].next[j];
}
node[index].judge = true;
node[index].sign = a;
}
void FindTree(char *s,int len){//查找
int index = 0;
for(int i = 0;i<len;i++){
int j = s[i] - '0';
index = node[index].next[j];
if(node[index].judge){
printf("%c",node[index].sign);//输出
mm++;
if(mm==n)break;//达到限制跳出
index = 0;
}
}
printf("\n");
}
int main()
{
int T;
init();
scanf("%d",&T);
while(T--){
mm = 0;
tot = 0;
CreatTree();
scanf("%d%d",&n,&m);
for(int i = 0;i<m;i++){
char str[20];
int name;
scanf("%d%s",&name,str);
InsertTree(name,str);//对应规则保存到字典树
}
scanf("%s",compare);
int l = 0;
int ll = strlen(compare);
for(int i = 0;i<ll;i++){
if(compare[i]>='a'&&compare[i]<='f')compare[i]-=32;//小写转换大写
for(int j = 0;j<4;j++){
ans[l++] = hexd[rela[compare[i] - '0']][j];//16进制转换为对应2二进制保存
}
}
ans[l] = '\0';
int p = 0;
int num = 0;
for(int i = 0;i<l;i++){//处理串
if((i+1)%9==0){
if(((p%2==1)&&ans[i]=='0')||((p%2==0)&&ans[i]=='1')){//决定是否保存
for(int j = i-8;j<i;j++){
sum[num++] = ans[j];
}
}
p = 0;
}
else if(ans[i]=='1')p++;
}
sum[num] = '\0';//sum是最终串
FindTree(sum,num);//输出
}
return 0;
}