字典树

本文介绍了字典树(Trie)的实现方法,并通过两个具体示例:单词化简(T1)和电话号码列表(T2),展示了其在实际问题解决中的应用。文章详细解释了插入操作和深度优先搜索的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

将信息以边的形式储存,如:
       0
    a / \ b
     1    2
  c / \d  | e
   3  4   5
查询“ac”时,遍历0-1-3。
T1 单词化简

#include<cstdio>
#include<iostream>
using namespace std;
int n, tri[2505][30], len;
string s[52];
void insert(const int x) {
	int p = 0;
	for(int i = 0; i < s[x].length(); i ++) {
		int v = s[x][i] - 'a' + 1;
		if(! tri[p][v]) {
			tri[p][v] = ++ len;//B
			tri[p][0] ++;//A
		}
		p = tri[p][v];
	}
}
void dfs(const int x) {
	int p = 0;
	char tmp = 0;
	for(int i = 0; i < s[x].length(); i ++) {
		int v = s[x][i] - 'a' + 1;
		if(tri[p][0] != 1)
			tmp = i;
		p = tri[p][v];
	}
	for(int i = 0; i < s[x].length(); i ++) {
		printf("%c", s[x][i]);
		if(i == tmp)
			break;
	}
	printf("\n");
}
int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++) {
		cin >> s[i];
		insert(i);
	}
	for(int i = 1; i <= n; i ++) {
		dfs(i);
	}
	return 0;
}

A:0号位起到统计儿子的作用,注意:前面的v因此要+1。
B:创建新的编号来存字母,注意:后面p=tri[p][v]不能写为p=len。
T2 Phone List

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int len, T, n, tri[100010][13];
string s;
bool f, in[100010];
void insert() {
	int p = 0;
	for(int i = 0; i < s.length(); i ++) {
		int v = s[i] - '0' + 1;
		if(! tri[p][v]) {
			tri[p][v] = ++ len;
			tri[p][0] ++;
		}
		p = tri[p][v];
	}
	in[p] = 1;
}
void dfs(const int x) {
	if(f || tri[x][0] == 0)
		return;
	if(in[x]) {
		printf("NO\n");
		f = 1;
		return;
	}
	for(int i = 1; i <= 10; i ++)
		if(tri[x][i])
			dfs(tri[x][i]);
}
int main() {
	scanf("%d", &T);
	while(T --) {
		f = 0;
		len = 0;
		scanf("%d", &n);
		memset(tri, 0, sizeof(tri));
		memset(in, 0, sizeof(in));
		for(int i = 1; i <= n; i ++) {
			cin >> s;
			insert();
		}
		dfs(0);
		if(! f)
			printf("YES\n");
	}
	return 0;
}

其实就是找在0到被in[]标记过的点的路径中有没有被in[]标记过的点。利用之前的tri[p][0]判断是否为末端点就行了。PS:记得清0!

还算简单吧?如果有问题,请在评论区指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值