00:00:00
一、简单介绍 字典树
树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。 它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

二、代码实现
I.字符串转数函数
为了更好地储存字符,我们需要将其转换为数字存入数组里。
这里想必不必多说,能学到这的大佬都会......
注意:此处按题目需求而变化。
代码如下(示例):
cpp
int getnum(char x){ //字符转数
if(x>='A'&&x<='Z')
return x-'A'; //处理大写字母
else if(x>='a'&&x<='z')
return x-'a'+26; //处理小写字母
else return x-'0'+52; //处理数字
}II.插入函数
调入
上插入自定义函数(insert):
cpp
void insert(string s) { //插入字符串
int p=0;
for(int i=0;i<s.size();i++) {
int tmp=getnum(s[i]);
if(!f[p][tmp]) f[p][tmp]=++idx; //如果不存在则插入
p=f[p][tmp]; //继续往下查找
cnt[p]++; //打标记1
}
cnt2[p]++; //打标记2
}III.查询函数
经过插入字符串后,便可依次查询字符串,走到对应的点输出维护的值,如以前没有插入过,则直接
cpp
int qurey(string s) { //查找函数
int p=0;
for(int i=0;i<s.size();i++) {
int tmp=getnum(s[i]);
if(!f[p][tmp])
return 0; //不存在,直接退出返回
p=f[p][tmp]; //存在继续往下走
}
return cnt[p]; //返回次数
}IV.删除函数
走到字符串对应的点后,用该点维护的值减掉它两个子树维护的值,就可以得到所有字符串
cpp
void del(string s){
int p=0;
for(int i=0;i<s.size();i++){
int tmp=s[i]-'0';
if(!f[p][tmp])
return;
p=f[p][tmp];
}
int v=cnt[p],vls=0,vrs=0;
if(f[p][0]) vls=cnt[f[p][0]];
if(f[p][1]) vrs=cnt[f[p][1]];
v-=vls+vrs; //根据前缀和做差 答案等于s这个点减左右子树两个点之和
if(v==0) return;
p=0;
for(int i=0;i<s.size();i++){
int tmp=s[i]-'0';
p=f[p][tmp];
cnt[p]-=v;
}
}IIV.完整代码
Code
cpp
#include<bits/stdc++.h>
using namespace std;
const int N=3e4+10;
const int M=100;
int t,n,q,f[N][M],cnt[N],idx;
string s;
int getnum(char x){
if(x>='A'&&x<='Z')
return x-'A';
else if(x>='a'&&x<='z')
return x-'a'+26;
else return x-'0'+52;
}
void reset_() {
for(int i=0;i<idx;i++) {
cnt[i]=0;
for(int j=0;j<M;j++)
f[i][j]=0;
}
}
void insert(string s) {
int p=0;
for(int i=0;i<s.size();i++) {
int tmp=getnum(s[i]);
if(!f[p][tmp]) f[p][tmp]=++idx;
p=f[p][tmp];
cnt[p]++;
}
}
void qurey(string s) {
int p=0;
for(int i=0;i<s.size();i++) {
int tmp=getnum(s[i]);
if(!f[p][tmp]) {
printf("0\n");
return ;
}
p=f[p][tmp];
}
printf("%d\n",cnt[p]);
return;
}
int main() {
scanf("%d",&t);
while(t--) {
reset_();
idx=0;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) {
cin>>s;
insert(s);
}
for(int i=1;i<=q;i++) {
cin>>s;
qurey(s);
}
}
return 0;
}总结
用途:
蒟蒻自我总结,可以忽略
有三大种 :
一、查询字符串是否出现过。
二、寻找该字符串的公共前缀。
三、用于进行 xor(异或)运算。
这是一种时间效率上比较高的树形结构。
题库
刚刚入门可以先浅浅练练,建议可以参考一下我的题单 洛谷【并查集】 ID:970993