Loading

「学习笔记」字典树(Trie)

最近补知识点补疯了!
字典树,顾名思义,就是一棵像字典的树
这棵字典树从根节点到某一结点,这一路径就构成了一个字符串,放张图

image

该图片来自 \(\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;
}
posted @ 2023-01-08 19:02  yi_fan0305  阅读(45)  评论(0编辑  收藏  举报