什么是 T i r e Tire Tire树
T
i
r
e
Tire
Tire树,即字典树,可以用来高效存储和查找字符串。
在上面的题目中,如果暴力去对于每个
p
p
p在
n
n
n中搜索显然会十分耗时,这时候我们就可以使用
T
i
r
e
Tire
Tire树来解决这种字符串查找的问题
T i r e Tire Tire树介绍
建树
以一个空结点为根节点,将字符串的各个字母按先后顺序依次连到树上。举个栗子,将
a
b
c
abc
abc和
a
d
e
ade
ade插入树中
可以观察到,
T
i
r
e
Tire
Tire顺着根节点出发,沿任意一条子树走到底都为一个已经存储好的字符串,对于拥有相同前缀的字符串,并不需要建立新的子树,而是在第一个不同的位置开始建立分支即可。但是为了存储相同前缀的字符串的个数,我们使用一个数组
c
n
t
[
x
]
cnt[x]
cnt[x]来表示到第
x
x
x这个结点前缀相同的字符串的数量
建树代码
void insert(char s[]){
int p = 0;
for(int i = 0; i < strlen(s); i++){
int nu = get_num(s[i]); //get_num()将一个字符转化为对应数字
if(!tr[p][nu]) tr[p][nu] = ++ids;
p = tr[p][nu];
cnt[p] ++;
}
}
查询
对于一个需要查询的字符串,直接从根节点出发,按照字母顺序走下去,返回最后节点的 c n t cnt cnt值即可
int find(char s[]){
int p = 0;
for(int i = 0; i < strlen(s); i++){
int nu = get_num(s[i]);
if(!tr[p][nu]) return 0; //如果到某一位已经没有相同前缀的字符串了,则没有必要继续
p = tr[p][nu];
}
return cnt[p];
}
总体来说
T
r
i
e
Trie
Trie树是比较简单的数据结构
A
C
c
o
d
e
AC code
ACcode
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 3e5 + 10;
int idx = 0;
int map[MAXN][100];
int cnt[MAXN];
inline int read(){
int n = 0,l = 1;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-') l = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
n = (n << 1) + (n << 3) + (c & 15);
c = getchar();
}
return n * l;
}
inline int get_num(char c){
if(c >= 'A' && c <= 'Z') return c - 'A';
if(c >= 'a' && c <= 'z') return c - 'a' + 26;
return c - '0' + 52;
}
void insert(char s[]){
int p = 0;
for(int i = 0; i < strlen(s); i ++){
int c = get_num(s[i]);
if(!map[p][c]) map[p][c] = ++idx;
p = map[p][c];
cnt[p] ++;
}
}
inline int find(char s[]){
int p = 0;
for(int i = 0; i < strlen(s); i ++){
int c = get_num(s[i]);
if(!map[p][c]) return 0;
p = map[p][c];
}
return cnt[p];
}
int main(){
int T = read();
while(T --){
for(int i = 0; i < idx; i ++)
for(int j = 0; j < 65; j ++)
map[i][j] = 0;
for(int i = 0; i < idx; i ++)
cnt[i] = 0;
idx = 0;
int n = read(),p = read();
char s[MAXN];
for(int i = 0; i < n; i ++){
scanf("%s",&s);
insert(s);
}
for(int i = 0; i < p; i ++){
scanf("%s",&s);
printf("%d\n",find(s));
}
}
return 0;
}