字典树专题复习 洛谷P2580 hdu4825 杭电多校1 1006

Trie又称字典树,前缀树

 

  • Trie的根节点是空的
  • 除根节点外,每个节点储存一个单词/字母
  • 也就是说,从根节点到每个单词节点的路径上的所有字母连接而成的字符串就是该节点对应的字符串
  • 每个非叶子结点一般都会被多次使用,以节省遍历时的时间效率
  • 另外,每个节点下面的数字是他们的编号

洛谷P2580

题目背景

XS中学化学竞赛组教练是一个酷爱炉石的人。

他会一边搓炉石一边点名以至于有一天他连续点到了某个同学两次,然后正好被路过的校长发现了然后就是一顿欧拉欧拉欧拉(详情请见已结束比赛 CON900)。

题目描述

这之后校长任命你为特派探员,每天记录他的点名。校长会提供化学竞赛学生的人数和名单,而你需要告诉校长他有没有点错名。(为什么不直接不让他玩炉石。)

输入格式

第一行一个整数 nnn,表示班上人数。

接下来 nnn 行,每行一个字符串表示其名字(互不相同,且只含小写字母,长度不超过 505050)。

第 n+2n+2n+2 行一个整数 mmm,表示教练报的名字个数。

接下来 mmm 行,每行一个字符串表示教练报的名字(只含小写字母,且长度不超过 505050)。

输出格式

对于每个教练报的名字,输出一行。

如果该名字正确且是第一次出现,输出 OK,如果该名字错误,输出 WRONG,如果该名字正确但不是第一次出现,输出 REPEAT

思路 字典树裸体

用val数组记录每个名字出现的次数

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int t,n,m,k;
int a[maxn*40][27];
int s[maxn];
int val[maxn*40];
int res;
int len=0;
int cnt=0;
char c[maxn];
int idx(char cs){return cs-'a'+1;}
void insert()
{
	len=strlen(c+1);
	int u=0;
	//cout<<len<<endl;
	for(int i=1;i<=len;i++)
	{
		int cc=idx(c[i]);
		//cout<<cc;
		if(!a[u][cc])
		{
			//cout<<cc<<endl;
			a[u][cc]=++cnt;
			//cout<<cnt<<endl;
		}
		//cout<<cnt<<endl;
		u=a[u][cc];
	}
	//cout<<1;
	//val[u]=v;
}
int find()
{
	int u=0;
	len=strlen(c+1);
	//cout<<len<<endl;
	for(int i=1;i<=len;i++)
	{
		int cc=idx(c[i]);
		//cout<<cc<<endl; 
		if(!a[u][cc])
		{
			return -1;
		}
		else 
		{
			u=a[u][cc];
		}
		
	}
	if(val[u]==0)
	{
		val[u]=1;
		return 1;
	}
	else if(val[u])
	{
		return 2;
	}
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		
		scanf("%s",c+1);
		insert();
		
	}
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		scanf("%s",c+1);
		int sign=find();
		if(sign==-1)
		{
			cout<<"WRONG"<<endl;
		}
		else if(sign==1)
		{
			cout<<"OK"<<endl;
		} 
		else 
		{
		 	cout<<"REPEAT"<<endl;
		}
	}
	return 0;
}

 hdu4825

Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?

Input

输入包含若干组测试数据,每组测试数据包含若干行。
输入的第一行是一个整数T(T < 10),表示共有T组数据。
每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。

Output

对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
对于每个询问,输出一个正整数K,使得K与S异或值最大。

Sample Input

2
3 2
3 4 5
1
5
4 1
4 6 5 6
3

Sample Output

Case #1:
4
3
Case #2:
4

运用01字典树

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn*40][4];
int jl[maxn*40];
int tag[maxn*40];
int t,n,m,s;
int cnt=0;
void insert(int x)
{
	int u=0;
	for(int i=31;i>=0;i--)
	{
		int xx=(x>>i)&1;
		//cout<<u<<" "<<xx<<" "<<a[u][xx]<<endl;
		if(a[u][xx]==0)
		{
			a[u][xx]=++cnt;
		}
		u=a[u][xx];
		
		if(i==2)
		{
			//cout<<
			//cout<<xx<<" "<<x<<" "<<u<<endl;
		}
		//if(i==2&&xx==0)cout<<u<<endl;
	}
	tag[u]=x;
}
int find(int k)
{
	int u=0;
	for(int i=31;i>=0;i--)
	{
		int kk=(k>>i)&1;
		//int xx=(x>>i)&1;
		//if()
			//if(i==2&&kk==1)cout<<kk<<" "<<u<<" "<<a[u][0]<<endl<<endl;
			if(a[u][kk^1])
			{
				u=a[u][kk^1];//尽量找与其相反的数 这可以让异或的值最大
			}
			else 
			{
				u=a[u][kk];
			}
			//if(i==2)cout<<kk<<" "<<u<<" "<<a[u][kk^1]<<endl<<endl;
		//cout<<u<<endl;
		//if(u==0)cout<<"11"<<endl;
	}
	return tag[u];
}
int main()
{
	cin>>t;
	int ss=0;
	while(t--)
	{
		cin>>n>>m;
		for(int i=0;i<=cnt;i++)
		{
			a[i][0]=0;
			a[i][1]=0;
			tag[i]=0;
		}
		cnt=0;
		for(int i=1;i<=n;i++)
		{
			int tmp;
			scanf("%d",&jl[i]);
			insert(jl[i]);
		}
		cout<<"Case #"<<++ss<<":"<<endl;
		for(int i=1;i<=m;i++)
		{
			scanf("%d",&s);
			int k=find(s);
			cout<<k<<endl;
		}
	}
	return 0;
}

杭电多校1 1006 / hdu6971

Xor sum

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1714    Accepted Submission(s): 305


 

Problem Description
Given a sequence of integers of length n, find the shortest consecutive subsequence witch XOR sum not less than k.

If there are multiple consecutive subsequences of the same length, print the consecutive subsequence with the smallest left end point.

If there are no consecutive subsequence witch XOR sum not less than k, just print "-1".

Input
The first line contains a single integer t (t<=100) representing the number of test cases in the input. Then t test cases follow.

The first line of each test case contains two integers n (1<=n<=100000) and k (0<=k<2^30), representing the length of sequence.

The second line of each test contains n integers ai (0<=ai<2^30), representing the integers in sequence.

The number of test witch n>1000 does not exceed 5.

Output
For each test case, print two integers in one line, representing the left end point and right end point of the consecutive subsequence.

If there are no consecutive subsequence witch XOR sum not less than k, print "-1" in one line.

Sample Input
 
 
2 3 2 1 2 2 9 7 3 1 3 2 4 0 3 5 1

Sample Output
 
 
2 2 5 7

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值