ACM-ICPC 2018 沈阳赛区网络预赛 I.Lattice's basics in digital electronics(模拟+01字典树)

题目

最后输出字符最多m个(m<=1e5),有n(n<=256)个加密条文,

第i个条文由一个ASCII值Ci,对应一段01字符串Si(|Si|<=10),

任一个字符串都不会是另一个的前缀

以下输入一个16进制的data串(|data|<=2e5)(含大小写字母A/a-F/f)

将data九位九位地数,去掉最后剩下的余数位;

每九位的第九位为校验位,对前八位进行奇校验

若这九位的1的个数为奇数,则保留前八位,否则舍弃;

对于保留下的01串,将其按加密条文对应表解密,并取其前m位输出

思路来源

https://blog.csdn.net/Originum/article/details/82530717

题解

凯神的题解还是写得很详细鸭,让自己更好地模拟了一下题意

校验看似复杂,实则不到10行就能搞过去

map那里其实不怎么会写简易的版本,就生生映射了一下

匹配时,在01字典树上匹配,成功匹配后就返回根rt

心得

终于能手敲01字典树的数组版本了

感觉过了几个月之后,自己对于某些知识的理解终于加深了

似乎熟练掌握一个领域的知识,至少在学习这个知识3个月后,还是菜啊.jpg

所幸自己上个学期开了挺多新知识的

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2600;
const int maxm=1e6+10; 
int t,m,n,rt;
int tr[maxn*2][2],cnt;
int num[maxn*2],len;
int tot,v;
string s,ans,res;
char ch[260];
map<char,string>to;
void init()
{
	to['0']="0000";
	to['1']="0001";
	to['2']="0010";
	to['3']="0011";
	to['4']="0100";
	to['5']="0101";
	to['6']="0110";
	to['7']="0111";
	to['8']="1000";
	to['9']="1001";
	to['A']="1010";
	to['B']="1011";
	to['C']="1100";
	to['D']="1101";
	to['E']="1110";
	to['F']="1111";
	to['a']="1010";
	to['b']="1011";
	to['c']="1100";
	to['d']="1101";
	to['e']="1110";
	to['f']="1111";
}
void add(int rt,string s,int id)
{
	int len=s.size();
	for(int i=0;i<len;++i)
	{
		int v=s[i]-'0';
		if(!tr[rt][v])
		tr[rt][v]=++cnt;
		rt=tr[rt][v];
	}
	num[rt]=id;
}
void find(string s)
{
	int rt=0;
	int len=s.size();
	for(int i=0;i<len;++i)
	{
		int v=s[i]-'0';
		rt=tr[rt][v];
		if(num[rt])
		{
			putchar(ch[num[rt]]);
			m--;
			if(!m)break;//最多输出m个字符 
			rt=0;
		}
	}
	puts("");
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	init();
	cin>>t;
	while(t--)
	{
		rt=cnt=0;
		memset(tr,0,sizeof tr);
		memset(num,0,sizeof num);
		cin>>m>>n; 
		for(int i=1;i<=n;++i)
		{
			cin>>v>>s;
			ch[i]=v;
			add(rt,s,i);
		}
		cin>>s;
		len=s.size();
		res.clear();
		for(int i=0;i<len;++i)
		res+=to[s[i]];
		len=res.size();
		ans.clear();
		for(int i=0;i<len/9*9;i+=9)
		{
			tot=0;
			for(int j=0;j<=8;++j)
			if(res[i+j]=='1')tot++;
			if(tot%2==0)continue;//奇校验 
			for(int j=0;j<=7;++j)
			ans+=res[i+j];
		}
		//cout<<ans<<endl;
		find(ans);
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code92007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值