简介
Trie 树, 又称字典树,单词查找树。它来源于retrieval(检索)中取中间四个字符构成(读音同try)。用于存储大量的字符串以便支持快速模式匹配。主要应用在信息检索领域。
复杂度分析
Trie树其实是一种用空间换时间的算法,前面也提到过,它占用的空间一般很大,但时间是非常高效的,插入和查询的时间复杂度都是O(l)的,总体来说还是很优秀的
先来看看这个树的样子
简单的说就是把字符串的每个字符存在树中,插入字符串时相同的字符可以不再输入,只需从不同的字符开始重新创建新的树节点。查询字符串时只需遍历树就能快速知道所查询的字符串存在与否。
看到这相信大家都发现一个问题,以上面的树为例,树中已经存在“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;
}
}