《算法竞赛进阶指南》0x10字典树

本文介绍了PhoneList和SecretMessage两种算法,前者利用字符串构建哈希树进行立即可读性判断,后者则处理数字序列并检查其在给定集合中的位置。通过实例展示了如何在字符串和数字序列中进行高效查询和判断。
Phone List
#include <bits/stdc++.h>
using namespace std;

const int N = 1e4 + 10;
int T, n;
int son[N * 10][10], idx, h[N * 10];			//n个长度不超过10的字符串,则总字符数不超过N * 10 
string s[N];

void insert(string s) {
	int u = 1;									//1为根结点 
	for (int i = 0; i < s.size(); i ++) {
		int j = s[i] - '0';
		if (son[u][j] == 0) son[u][j] = ++ idx;	//如果该结点没有编号,则分配一个编号 
		u = son[u][j];							//如果该结点有编号,则获取这个编号 
	}
	h[u] ++;									//在该结点处结尾的数字数量 +1 
}

//判断其它数字串是否是s的前缀 
bool query(string s) {
	int u = 1, cnt = 0;
	for (int i = 0; i < s.size(); i ++) {
		int j = s[i] - '0';
		u = son[u][j];								
		cnt += h[u];
	}
	if (cnt > 1) return true;
	else return false;					
}

int main() {
	scanf("%d", &T);
	while (T --) {
		scanf("%d", &n);
		
		memset(son, 0, sizeof(son));
		memset(h, 0, sizeof(h));
		idx = 1;
		
		for (int i = 1; i <= n; i ++) {
			cin >> s[i];
			insert(s[i]);
		}
		
		bool flag = false;
		for (int i = 1; i <= n; i ++) {
			if (query(s[i])) {
				flag = true;
			}
		}
		if (flag) puts("NO");				//注意输出要求 
		else puts("YES");
	}
	
	return 0;
}
Immediate Decodability
#include <bits/stdc++.h>
using namespace std;

string s, a[10];
int n, t;
int idx = 1, son[100][10], h[100];

void insert(string s) {
	int u = 1;
	for (int i = 0; i < s.size(); i ++) {
		int j = s[i] - '0';
		if (!son[u][j]) son[u][j] = ++ idx;
		u = son[u][j];
	}
	h[u] ++;
}

bool query(string s) {
	int u = 1, cnt = 0;
	for (int i = 0; i < s.size(); i ++) {
		int j = s[i] - '0';
		u = son[u][j];
		cnt += h[u];
	}
	if (cnt > 1) return true;	//存在,not 
	else return false;			//不存在 
}

int main() {
	while (cin >> s) {
		if (s != "9") {
			a[++ n] = s;			
			insert(s);
		}
		else {
			++ t;
			bool flag = false;
			for (int i = 1; i <= n; i ++) {
				if (query(a[i])) {
					flag = true;
					break;
				}
			}
			
			if (flag) printf("Set %d is not immediately decodable\n", t);
			else printf("Set %d is immediately decodable\n", t);
			
			memset(son, 0, sizeof(son));
			memset(h, 0, sizeof(h));
			n = 0;
			idx = 1;
		}
	}

	return 0;
}
Secret Message 秘密信息
#include <bits/stdc++.h>
using namespace std;

const int N = 5e5 + 10;
int n, m;
int t, a[N];
int son[N][2], idx = 1, ed[N], pass[N];

void insert() {
	scanf("%d", &t);
	for (int i = 1; i <= t; i ++) scanf("%d", &a[i]);
	
	int u = 1;
	for (int i = 1; i <= t; i ++) {
		int j = a[i];
		if (!son[u][j]) son[u][j] = ++ idx;
		u = son[u][j];
		pass[u] ++;
	}
	ed[u] ++;
}

int query() {
	scanf("%d", &t);
	for (int i = 1; i <= t; i ++) scanf("%d", &a[i]);
	
	int u = 1, res = 0;
	for (int i = 1; i <= t; i ++) {
		int j = a[i];
		if (!son[u][j]) return res;
		u = son[u][j];
		res += ed[u];
	}
	return res + pass[u] - ed[u];
}

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i ++) {
		insert();
	}

	for (int i = 1; i <= m; i ++) {
		printf("%d\n", query());
	}

	return 0;
}
L语言
#include <bits/stdc++.h>
using namespace std;

int n, m;
int son[210][26], h[210], idx;
char s[2000000], f[2000000];

void insert(int st) {
	int u = 1;
	for (int i = st; s[i]; i ++) {
		int j = s[i] - 'a';
		if (!son[u][j]) son[u][j] = ++ idx;
		u = son[u][j];
	}
	h[u] = 1;
}

int query(int st) {
	if (f[st]) return f[st];
	
	int u = 1, res = 0;
	for (int i = st; s[i]; i ++) {
		int j = s[i] - 'a';
		if (!son[u][j]) break;
		u = son[u][j];
		if (h[u]) res = max(res, i + 1 - st + query(i + 1));
	}
	f[st] = res;
	return res;
}

int main() {
	scanf("%d%d", &n, &m);
	idx = 1;
	while (n --) {
		scanf("%s", s);
		insert(0);
	}
	
	while (m --) {
		memset(f, 0, sizeof(f));
		scanf("%s", s);
		printf("%d\n", query(0));
	}

	return 0;
}
The XOR Largest Pair
#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int n, a[N], maxx;
int son[N * 31][2], h[N * 31], idx = 1;

void insert (int x) {
	int u = 1;
	for (int i = 30; i >= 0; i --) {
		int j = (x >> i) & 1;
		if (son[u][j] == 0) son[u][j] = ++ idx;
		u = son[u][j];
	}
	h[u] = x;
}

int query(int x) {
	int u = 1, res = 0;
	for (int i = 30; i >= 0; i --) {
		int j = (x >> i) & 1;
		if (son[u][!j]) u = son[u][!j];
		else u = son[u][j];
	}
	return x ^ h[u];
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i ++) cin >> a[i], insert(a[i]);
	
	for (int i = 1; i <= n; i ++) {
		maxx = max(maxx, query(a[i]));
	}
	cout << maxx;

	return 0;
}
The xor-longest Path
#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int n;
int h[N], to[N * 2], wt[N * 2], ne[N * 2], m;
int a[N], son[N * 31][2], val[N * 31], idx;

void add(int u, int v, int w) {
	to[++ m] = v; wt[m] = w; ne[m] = h[u]; h[u] = m;
}

void dfs(int u, int fa, int sum) {
	a[u] = sum;
	
	for (int i = h[u]; i > 0; i = ne[i]) {
		int j = to[i];
		if (j != fa) {
			dfs(j, u, sum ^ wt[i]);
		}
	}
}

void insert(int x) {
	int u = 1;
	for (int i = 30; i >= 0; i --) {
		int j = x >> i & 1;
		if (!son[u][j]) son[u][j] = ++ idx;
		u = son[u][j];
	}
	val[u] = x;
}

int query(int x) {
	int u = 1;
	for (int i = 30; i >= 0; i --) {
		int j = x >> i & 1;
		if (son[u][!j]) u = son[u][!j];
		else u = son[u][j];
	}
	return x ^ val[u];
}

int main() {
	cin >> n;
	for (int i = 1; i < n; i ++) {
		int u, v, w;
		cin >> u >> v >> w;
		add(u, v, w); add(v, u, w);
	}
	
	dfs(1, 0, 0);
	
	idx = 1;
	for (int i = 1; i <= n; i ++) insert(a[i]);
	
	int maxx = 0;
	for (int i = 1; i <= n; i ++) {
		maxx = max(maxx, query(a[i]));
	}
	cout << maxx;
	
	return 0;
}
Codechef REBXOR
#include <bits/stdc++.h>
using namespace std;

const int N = 4e5 + 10;
int n, a[N], w[N], l[N], r[N];
int son[N * 31][2], idx;

void insert(int x) {
	int u = 1;
	for (int i = 30; i >= 0; i --) {
		int j = x >> i & 1;
		if (!son[u][j]) son[u][j] = ++ idx;
		u = son[u][j];
	}
}

int query(int x) {
	int u = 1, res = 0;
	for (int i = 30; i >= 0; i --) {
		int j = x >> i & 1;
		if (son[u][!j]) u = son[u][!j], res += (1 << i);
		else u = son[u][j];
	}
	return res;
}

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i ++) {
		scanf("%d", &a[i]);
		w[i] = w[i - 1] ^ a[i];
	}
	
	memset(son, 0, sizeof(son));
	idx = 1;
	insert(0);
	for (int i = 1; i <= n; i ++) {
		l[i] = max(l[i - 1], query(w[i]));
		insert(w[i]);
	}
	
	memset(son, 0, sizeof(son));
	idx = 1;
	insert(0);
	for (int i = n; i >= 1; i --) {
		r[i] = max(r[i + 1], query(w[i]));
		insert(w[i]);
	}
	
	int maxx = 0;
	for (int i = 1; i < n; i ++) {
		maxx = max(maxx, l[i] + r[i + 1]);
	}
	printf("%d", maxx);	
	
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值