Trie
什么是 Trie
Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较。
核心思想
Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
注意 !
-
Trie 是将字符存储在树的边上, 节点是用来记录信息的
-
Trie 的根节点为 0
代码实现
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
const int root=0; // 默认 Trie 根节点位置为 0
/* trie[i][j] i 记录当前节点位置, 同样只关注指向下一个节点的相对位置, j 是表征当前节点下一个字母的指针
合起来是当前节点为 i 下一个字母对应编码为 j 的下一个节点的位置为 trie[i][j]
当前树只存储 26 位小写字母构成的string
*/
int trie[N][26]; // 存储 Trie
int sz=0; // Trie 大小
int val[N]; // Trie 节点信息
void init(){
sz=1;
memset(trie,0,sizeof(trie));
memset(val,0,sizeof(val));
}
// 将字符串插入 Trie
void insert_str(const string& str){
int ch,pos=root;
for(int i=0;i<str.size();i++){
ch=str[i]-'a';
if(!trie[pos][ch]) trie[pos][ch]=++sz;
pos=trie[pos][ch];
}
val[pos]=1;
/* val[pos] 的更新
可以放到 for 循环内,也可以放到 for 循环外面,根据不同的题有不同的方法.
当在 for 循环内部时,用来表示的含义时 相同的前缀出现的次数.
当在外面的时候给 val 变成 1 或 -1 表示这个串到这里结束。
*/
}
// 查询字符串 str 是否出现过
bool query_str(const string& str){
int ch,pos=root;
for(int i=0;i<str.size();i++){
ch=str[i]-'a';
if(!trie[pos][ch]) return false;
pos=trie[pos][ch];
}
return val[pos];
}
int main()
{
ios::sync_with_stdio(0);
clock_t c1 = clock();
#ifdef LOCAL
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
#endif
// ======================================================================
int n,q;
string tmp;
init();
cin>>n>>q;
while(n--){
cin>>tmp; insert_str(tmp);
}
while(q--){
cin>>tmp;
if(query_str(tmp)) puts("Existed!");
else puts("Not yet!");
}
// ======================================================================
end:
cerr << "Time Used:" << clock() - c1 << "ms" << endl;
return 0;
}
/*
输入:
7 2
dgsdbc
zfhdfaaa
absfs
xbcc
vbgdch
syqwq
fgwctc
syqwq
fgwsyq
输出:
Existed!
Not yet!
*/