欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Trie树(字典树,单词查找树)

程序员文章站 2024-02-08 22:02:04
...

简介

Trie 树, 又称字典树,单词查找树。它来源于retrieval(检索)中取中间四个字符构成(读音同try)。用于存储大量的字符串以便支持快速模式匹配。主要应用在信息检索领域。

复杂度分析

Trie树其实是一种用空间换时间的算法,前面也提到过,它占用的空间一般很大,但时间是非常高效的,插入和查询的时间复杂度都是O(l)的,总体来说还是很优秀的

先来看看这个树的样子
Trie树(字典树,单词查找树)
简单的说就是把字符串的每个字符存在树中,插入字符串时相同的字符可以不再输入,只需从不同的字符开始重新创建新的树节点。查询字符串时只需遍历树就能快速知道所查询的字符串存在与否。

看到这相信大家都发现一个问题,以上面的树为例,树中已经存在“and”,但是我们查询“an”时,也会判定为存在,所以我们插入字符串时需要在字符串结尾时加一个结束判断的标记,这里我们通常用数组来实现。

先来看看树定义

// 0号点既是根节点,又是空节点
// son[][]存储树中每个节点的子节点
// cnt[]存储以每个节点结尾的单词数量
//sum代表数的节点数 
int son[N][26],cnt[N],sum;

插入函数

void insert(string str){
	int p=0;
	for(int i=0;str[i];i++){
		int u=str[i]-'a';
		if(!son[p][u]) //如果这个字符之前没有出现过
			son[p][u]=++sum;//创建新的树节点
		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;//如果未出现直接返回
		p=son[p][u];
	}
	return cnt[p];
}

下面是完整代码

#include<cstdio>
#include<string>
#include <cstring>
#include <iostream>
#include<algorithm> 
using namespace std;

// 0号点既是根节点,又是空节点
// son[][]存储树中每个节点的子节点
// cnt[]存储以每个节点结尾的单词数量
//sum代表数的节点数 

int son[N][26],cnt[N],sum;

void insert(string str){
	int p=0;
	for(int i=0;str[i];i++){
		int u=str[i]-'a';
		if(!son[p][u]) 
			son[p][u]=++sum;
		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;
		p=son[p][u];
	}
	return cnt[p];
}

int main()
{
	int n,m;
	cin>>n;
	string s;
	for(int i=0;i<n;i++){
		cin>>s;
		insert(s);
	}
	cin>>m;
	for(int i=0;i<m;i++){
		cin>>s;
		int ans=query(s);
		cout<<ans<<endl;
	}
}