字典树-01字典树
什么是字典树?
字典树,又叫前缀树,Trie树,通常被用作字符串匹配。
它的实现原理是什么?
先建立一颗树,对于这棵树上每个节点i与其后继节点间的连线,都有存入一个字符。
对于存图时,从0节点开始遍历,找到其与其他出现过的字符第前缀不同的地方,新增节点。代码如下:
int p = 0, k = 0;
for(int i = 0; i < str.length(); i++){
int t = str[i] - 'a';
if(!st[p][t]) st[p][t] = k++;
p = st[p][t];
}
以上代码,p为当前节点编号,k为新增节点编号。当查找到有不同的字符,由p指向t,新增节点k,k自增1作为下一节点,并将p更新到新增节点,以便后续字符的添加。
对于查询,则是相同的思路。代码如下:
int p = 0;
for(int i = 0; i < s.length(); i++){
if(!st[p][s[i] - 'a'])return -1;
p=st[p][s[i] - 'a'];
}
return 1;
若出现的字符不存在树中,直接返回-1,代表查询失败。全部查询结束,代表查询成功,返回1.
模板样例:
输入n,m,分别为字符串数量与查询字符串数量,接下来m+n行字符串
输出m行,若存在则输出"存在",否则输出"不存在".
输入样例
5 3
abccc
jcjcj
abaca
kacbd
kacbdaa
abc
aba
abd
输出样例
存在
存在
不存在
代码
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<string.h>
using namespace std;
int st[1005][30];
string str;
int k = 1;
void sett(string str) {
int p = 0;
for (int i = 0; i < str.length(); i++) {
int t = str[i] - 'a' + 1;
if (!st[p][t]) st[p][t] = k++;
p = st[p][t];
}
}
bool seac() {
cin >> str;
int p = 0;
for (int i = 0; i < str.length(); i++) {
int t = str[i] - 'a' + 1;
if (!st[p][t]) return false;
p = st[p][t];
}
return true;
}
int main() {
int n, m;
cin >> n >> m;
while (n--) {
cin >> str;
sett(str);
}
while (m--) {
if (seac())cout << "存在\n";
else cout << "不存在\n";
}
return 0;
}
什么是01字典树?
01字典树主要解决异或最值问题。
算法原理
同trie一样,将其中的字符转为0或1即可。
存图
int p = 0;
for(int i = 32; i >= 0; i--){
int t = (x >> i) & 1;
if(!st[p][t]) st[p][t]=k++;
p = st[p][t];
}
val[p]=x;
存图时,从为高位,每个链都有32层,是一个完全二叉树,以方便查询时对异或查找的便捷。
注:虽然图为32层,但是加入的节点(可查询节点的数量)只有你输入数字二进制为1的数量。因此不必担心查询过慢的问题。
查询
int p = 0;
for(int i = 32; i >= 0; i--){
int t = (x >> i) & 1;
if(!st[p][t]) p = st[p][t];//此处是根据计算异或的最大或最小值,按照贪心方法计算,若最大,优先找不同的点,反之则反
else p = st[p][t ^ 1];
}
return val[p];
代码
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<string.h>
typedef long long ll;
using namespace std;
int k = 1;
int st[10005][2];
int val[10005];
void insert(int x){
int p = 0;
for(int i = 32; i >= 0; i--){
int t = (x >> i) & 1;
if(!st[p][t]) st[p][t]=k++;
p = st[p][t];
}
val[p]=x;
}
int seacher(int x){
int p = 0;
for(int i = 32; i >= 0; i--){
int t = (x >> i) & 1;
if(st[p][t ^ 1]) p = st[p][t ^ 1];
else p = st[p][t];
}
return val[p];
}
int main() {
int n;
cin>>n;
while(n--){
int a;
cin>>a;
insert(a);
}
int num;
cin>>num;
cout<<(seacher(num)^num)<<endl;
return 0;
}