「学习笔记」字典树(Trie)
最近补知识点补疯了!
字典树,顾名思义,就是一棵像字典的树
这棵字典树从根节点到某一结点,这一路径就构成了一个字符串,放张图
该图片来自 \(\texttt{OI-Wiki}\)
这个字典树用边来代表字母,\(1 \rightarrow 3 \rightarrow 7\) 代表着字符串 \(ba\),一般的只包含小写字母的字典树,是一个 \(26\) 叉树,但是字典树并不是都是 \(26\) 叉的,根据题目需要,有 \(2\) 叉的,有 \(52\) 叉的,等等。
字典树有插入 insert
和查找 find
两个操作,其实只要理解了上面的图,这些就都会了,每个节点都可以储存信息,根据题目要求来。
封装的 Trie
struct Trie {
int cnt;
int ch[N][62], cot[N];
inline void init() {
memset(ch[0], 0, sizeof ch[0]);
cot[0] = 0;
cnt = 0;
}
inline int getnum(const char x) {
if (x >= 'A' && x <= 'Z') {
return x - 'A';
}
if (x >= 'a' && x <= 'z') {
return x - 'a' + 26;
}
if (x >= '0' && x <= '9') {
return x - '0' + 52;
}
return 0;
}
inline void insert(const char s[]) {
int cur = 0, l = strlen(s);
for (int i = 0; i < l; ++ i) {
int c = getnum(s[i]);
if (!ch[cur][c]) {
ch[cur][c] = ++ cnt;
cot[cnt] = 0;
memset(ch[cnt], 0, sizeof ch[cnt]);
}
cur = ch[cur][c];
cot[cur] ++;
}
}
inline int find(const char s[]) {
int cur = 0, l = strlen(s);
for (int i = 0; i < l; ++ i) {
int c = getnum(s[i]);
if (!ch[cur][c]) return 0;
cur = ch[cur][c];
}
return cot[cur];
}
} trie;
洛谷模板题的完整代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read() {
ll x = 0;
int fg = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
fg |= (ch == '-');
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return fg ? ~x + 1 : x;
}
const int N = 3e6 + 5;
int T, cnt, n, q;
int ch[N][62], cot[N];
char s[N];
void init() {
for (int i = 0; i <= cnt; ++ i) {
cot[i] = 0;
for (int j = 0; j <= 61; ++ j) {
ch[i][j] = 0;
}
}
cnt = 0;
}
int getnum(char x) {
if (x >= 'A' && x <= 'Z') {
return x - 'A';
}
if (x >= 'a' && x <= 'z') {
return x - 'a' + 26;
}
if (x >= '0' && x <= '9') {
return x - '0' + 52;
}
return 0;
}
void insert(char s[]) {
int cur = 0, l = strlen(s);
for (int i = 0; i < l; ++ i) {
int c = getnum(s[i]);
if (!ch[cur][c]) {
ch[cur][c] = ++ cnt;
}
cur = ch[cur][c];
cot[cur] ++;
}
}
int find(char s[]) {
int cur = 0, l = strlen(s);
for (int i = 0; i < l; ++ i) {
int c = getnum(s[i]);
if (!ch[cur][c]) return 0;
cur = ch[cur][c];
}
return cot[cur];
}
void work() {
n = read(), q = read();
for (int i = 1; i <= n; ++ i) {
scanf("%s", s);
insert(s);
}
for (int i = 1; i <= q; ++ i) {
scanf("%s", s);
printf("%d\n", find(s));
}
}
int main() {
T = read();
while (T --) {
init();
work();
}
return 0;
}
朝气蓬勃 后生可畏