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

简介

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

复杂度分析

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

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

看到这相信大家都发现一个问题,以上面的树为例,树中已经存在“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
#include
#include 
#include 
#include 
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;
	}
}

你可能感兴趣的:(字符串,数据结构)