字典树入门小结

本文介绍了字典树的基础知识,包括如何建立Trie树、进行查询操作以及释放内存的方法。通过具体的代码实现展示了字典树的构建过程,并提供了查询操作的示例。此外,还提及了字典树在入门题目中的应用以及对学习的总结。

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

一、基础知识:

树状结构保存字符串,查找快,判断前缀快,保存数量大。

建Trie树:

逐一把每则单词的每个字母插入Trie。插入前先看前缀是否存在。如果存在,就共享,否则创建对应的节点和边

struct Trie
{
	int num;
	Trie *nx[N];	
};

num记录该前缀出现的次数,N是分支数,比如小写字母构成的单词的树N就是26,十进制的数字N就是10,二进制的01编码N就是2

具体建树代码:

Trie *root;
void init (Trie *t)
{
    for (int j = 0; j < N; ++j) //初始化
    {
        t->nx[j] = NULL;
    }
    t->num = 0;
}
void Insert (char str[])//插入单词
{
    Trie *p = root;
    int len = strlen (str);
    for (int i = 0; i < len; ++i)
    {
        int id = str[i] - 'a';
        if (p->nx[id] == NULL)
        {
            Trie *t = new Trie;
            init(t);
            p->nx[id] = t;
        }
        p = p->nx[id];
        p->num++;
    }
}


查询:

查询非常简单。比如要查找的单词是int,顺着路径i -> in -> int就找到了。遇到NULL就是没有return 0;就好

int Find(char str[])//查找前缀为str的单词数
{
    Trie *p = root;
    int cnt,len = strlen(str);
    for (int i = 0;i < len;++i)
    {
        int id = str[i] - 'a';
        if (p->nx[id] == NULL) return 0;
        p = p->nx[id];
        cnt = p->num;
    }
    return cnt;
}


释放:

另外关于内存的释放,貌似大多数题不写释放都能A

void Delete(Trie *t)
{
	for (int i = 0;i < N;++i)
	{
		if (t->nx[i]!=NULL) Delete(t->nx[i]);
	}
	delete t;
}

测试:

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 26;
struct Trie_Tree
{
	struct Trie 
	{
		int num; //前缀数 
		Trie *nx[N];//分支 
	} ;	
	Trie *root;
	void init(Trie *t) //初始化节点 
	{
		for (int i = 0;i < N;++i)
		{
			t->nx[i] = NULL;
		}
		t->num = 0;
	}
	void build()//初始化根 
	{
		root = new Trie;
    	init(root);
	} 
	void Insert(char word[]) //初始化单词
	{
		Trie *p = root;
		int len = strlen(word);
		for (int i = 0;i < len;++i)
		{
			int id = word[i] - 'a';//小写字母的单词就-'a'
			if (p->nx[id] == NULL) //没有就新建一个
			{
				Trie *t = new Trie;
				init(t);
				p->nx[id] = t;//建 
			} 
			p = p->nx[id];//往下走
			p->num++; 
		}
	} 
	int Find(char word[]) //查找前缀为word的单词数
	{
		Trie *p = root;;
		int cnt,len = strlen(word);
		for (int i = 0;i < len;++i)
		{
			int id = word[i] - 'a';
			if (p->nx[id] == NULL) return 0;//没有这样的前缀 
			p = p->nx[id];
			cnt = p->num;//其实cnt是最后一个字母的num 
		}
		return cnt;
	} 
	void Delete(Trie *t)
	{
		for (int i = 0;i < N;++i)
		{
			if (t->nx[i]!=NULL) Delete(t->nx[i]);
		}
		delete t;
	}
}text;
int main()
{
	/******************************************************
	测试:
		1.建立一个n个单词的字典树 
		2.对输入的m个前缀查找在字典树中出现的次数 
	******************************************************/ 
	text.build();
    int n,m;cin>>n>>m;
    char s[222];
    for (int i = 1;i <= n;++i) 
	{
		scanf("%s",s);
		text.Insert(s);
	}
	for (int i = 1;i <= m;++i)
	{
		scanf("%s",s);
		int t = text.Find(s);
		if (t) 
		{
			printf("%s shows %d times in the Trie \n",s,t);
		}
		else printf("%s does not exist in the Trie \n",s);
	}
	text.Delete(text.root);
    return 0;
}


运行结果:

































二、入门题目:

最基础的模板,求前缀串在Trie中出现的次数,直接建完树查询
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<stdlib.h>
#include<cctype>
#include<string>
using namespace std;
typedef long long ll;
#define Pintl(x) printf("%d\n",x)
const int N = 26;
struct Trie
{
    int num;
    Trie* nx[N];
};
Trie *root;
void init (Trie *t)
{
    for (int j = 0; j < N; ++j) //初始化
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值