Trie数 字典树 算法思想及代码实现

Trie树

Trie树又称字典树,是一种简单的树形数据结构,他的主要作用是高效地存储和查找字符串,其实现原理是利用字符串的公共前缀来减少查询时间,最大限度的减少无谓字符的比较,效率高。


三个基本性质

根节点不包含字符,除根节点外每一个节点都只包含一个字符;
从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
每个节点的所有子节点包含的字符都不相同。


存储规则

从根节点开始,存一个字符串,先看根节点连接的子结点有没有第一个字母,有的话接着从他往下找第二个字母,以此类推;若没有某一字母,就新建一个该字母节点,连进去,再依次往下新建。对于每个结尾字符要加一个标记,标记该字母是一个字符串的结尾,我们一般用计数做标记,每以他结尾一次计数就加一,这样不仅能实现标记,0是非结尾,非0是结尾;还能统计数量。存储图如下:
trie

若要存储左边的字符串,则建的trie树如右图所示


代码实现

int son[MAXN][26],cnt[N],idx;	//son就是存的trie树,只有26个字母,因此子结点最多只有26个,cnt是统计该结点作为结尾的次数,idx是每个节点的唯一编号
void insert(string str)		//插入函数
{
	int p = 0;	//根结点为0号,从根开始
	for(int i = 0;str[i];i++)	//循环字符串的每个字母
	{
		int u = str[i] - 'a';	//将字母转化为编号从0-25
		if(!son[p][u])	//如果没有u节点
			son[p][u] = ++idx;	//新建一个p的子结点为u,编号为idx
		p = son[p][u];	//当前结点往下走,如此循环
	}
	cnt[p]++;	//最终的结尾节点计数++
}

int query(string str)	//查询函数
{
	int p = 0;	//从根节点开始
	for(int i = 0;str[i];i++)	//循环查找的字符串的每一个字母
	{
		int u = str[i] - 'a';	//将字母转化为编号
		if(!son[p][u])	//如果没有该结点
			return 0;	//返回0
		p = son[p][u];
	}
	return cnt[p];		//返回结尾节点的个数
}

模板题

Acwing 835: Trie字符串统计

代码模板

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int N = 100010;

int son[N][26],cnt[N],n,idx;
string op,str;

void insert(string s)
{
    int p = 0;
    for (int i = 0;s[i]; i ++ )
    {
        int u = s[i] - 'a';
        if(!son[p][u])
            son[p][u] = ++idx;
        p = son[p][u];
    }
    cnt[p]++;
}

int query(string s)
{
    int p = 0;
    for(int i = 0;s[i];i++)
    {
        int u = s[i] - 'a';
        if(!son[p][u])
            return 0;
        p = son[p][u];
    }
    return cnt[p];
}

int main()
{
    cin >> n;
    for(int i = 0;i < n;i++)
    {
        cin >> op >> str;
        if(op == "I")
            insert(str);
        else
            cout << query(str) << endl;
    }
    
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值