字典树

P1481 魔族密码

思路
首先发现这个找相同前缀的操作类似字典树,所以考虑把 \(n\) 个字符串全都放到字典树上然后在每一次添加字符串时找一个最大的长度。
代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
const int N = 2e3+5;
int trie[N][26];
int word[N];
int n, tot = 0, ans = 0;
void insert(string s){
	int u=0;
	int len = s.size();
	int res=0;
	for(int i=0; i < len ; ++i){
		int a = s[i] - 'a';
		if(trie[u][a] == 0)
			trie[u][a] = ++tot;
		u = trie[u][a];
		res += word[u];
	}
	word[u]++;
	if(res + 1 > ans){
		ans = res + 1;
	}
}
int main(){
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	int n;
	cin >> n;
	for(int i=1; i<=n; ++i){
		string s;
		cin >> s;
		insert(s);
	}
	cout << ans;
	return 0;
}

P2580 于是他错误的点名开始了

思路
这道题是在问字符串是否存在以及查询的次数。考虑把每一次查询到且在字典树上存在的字符串打上查询次数的标记
代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
const int N = 5e5+5;
int trie[N][26], pos[N], tag[N], cnt;
void ins(string s){
	int len = s.size(), u=0;
	for(int i=0; i < s.size(); ++i){
		int idx = s[i] - 'a';
		if(!trie[u][idx])trie[u][idx] = ++cnt;
		u = trie[u][idx];
	}
	pos[u]++;
}
int qry(string s){
	int len = s.size(), u=0;
	for(int i=0; i < s.size(); ++i){
		int idx = s[i] - 'a';
		if(!trie[u][idx]){
			return -1;
		}
		u = trie[u][idx];
	}
	return pos[u]? tag[u]++ : -1;
}
int main(){
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	int n;
	cin >> n;
	for(int i=1; i<=n; ++i){
		string s;
		cin >> s;
		ins(s);
	}
	int m;cin >> m;
	for(int i=1; i<=m; ++i){
		int res;
		string s;
		cin >> s;
		res = qry(s);
		if(res == -1)cout << "WRONG\n";
		else if(res==0)cout << "OK\n";
		else cout << "REPEAT\n";
	}
	return 0;
}

P4551 最长异或路径

思路
先用一个dfs把图转变成几个不同长度的01链,然后把链放到字典树上去找最大异或。
代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
const int N = 1e5+5;
vector<pair<int, ll> > g[N];
int s[N], trie[N*31][2];
int n, tot;
void dfs(int u, int fa){
	for(auto dt : g[u]){
		int v = dt.first, w = dt.second;
		if(v != fa){
			s[v] = s[u] ^ w;
			dfs(v,u);
		}
	}
}
void ins(int val){
	int x=0;
	for(int i=(1<<30); i; i>>=1){
		int a = bool (val & i);
		if(!trie[x][a]){
			trie[x][a] = ++tot;
		}
		x = trie[x][a];
	}
}
int find(int val){
	int ans=0, x=0;
	for(int i = (1<<30); i ; i>>=1){
		int a = bool(val & i);
		if(trie[x][!a]){
			ans += i;
			x = trie[x][!a];
		}
		else{
			x = trie[x][a];
		}
	}
	return ans;
}
int main(){
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> n;
	for(int i=1; i<n; ++i){
		int u, v, w;
		cin >> u >> v >> w;
		g[u].push_back({v,w});
		g[v].push_back({u,w});
	}
	dfs(1,-1);
	for(int i=1; i<=n; ++i){
		ins(s[i]);
	}
	int ans=0;
	for(int i=1; i<=n; ++i){
		ans = max(ans, find(s[i]));
	}
	cout << ans;
	return 0;
}
posted @ 2026-09-21 23:53  williamYcY  阅读(10)  评论(0)    收藏  举报
/* */ /* */ /* */ /* */ /* */ /* */