什么是Trie树
Trie树,又称字典树,是一种树形结构。用于统计和排序大量的字符串(但不仅限于字符串)。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。
Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。但是Trie树的内存消耗非常大。
Trie树的实现
**例子:**对于"abana" “become” “insert” "abbb"建立的Trie树的样子为:
Tire树的插入:从根节点开始, 沿着单词中的每个字母对应的结点往下走,知道该单词遍历完,并且将最后的结点标记,表示该单词已经存储在了Trie树
代码实现:
int son[N][26], cnt[N], idx;
char str[N];
void insert( char str[])
{
int p = 0;// 从根节点开始
for ( int i = 0; str[i]; ++i)
{
int u = str[i] - 'a';
if ( !son[p][u] ) son[p][u] = ++ idx; // 如果不存在该结点就创建出来
p = son[p][u];// 继续往下走
}
cnt[p]++;//最后标记
}
查询:同插入操作相同,从根节点出发,当走到某节点与单词字母不匹配或者遍历完没有被标记,则表示该单词不在Trie树中。
代码实现:
int query( char 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]; // 当单词遍历完时,不存在返回的也是0,否则就是出现的次数
}
Trie树的应用
应用一:Trie字符串统计
思路:
利用Trie树结构,将要插入的字符串插入;进行查询操作即可AC
参考代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int son[N][26], cnt[N], idx;
char str[N];
void insert( char str[])
{
int p = 0;
for ( int i = 0; str[i]; ++i)
{
int u = str[i] - 'a';
if ( !son[p][u] ) son[p][u] = ++ idx;
p = son[p][u];
}
cnt[p]++;
}
int query( char 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;
scanf("%d",&n);
char op[2];
while(n--)
{
scanf("%s%s",op, str);
if(op[0] == 'I') insert(str);
else printf("%d\n",query(str));
}
return 0;
}
应用二:最大异或树
思路:
根据异或的不进位加法特点,我们可以把每个数的二进制表示插入到Trie中,然后对每个数进行查询操作,从而找出最大异或值具体可看代码
代码:
#include<iostream>
using namespace std;
const int N = 100010, M = 31 * N;
int n, idx, a;
int son[M][2];
void insert(int x)
{
int p = 0;
for (int i = 30; i >= 0; i--) //从高位存储
{
int u = x >> i & 1; // 找出改位是0还是1
if (!son[p][u]) son[p][u] = ++idx; // 如果这个结点不存在就创建出来
p = son[p][u]; // 继续往下走
}
}
int query(int x)
{
int p = 0, ans = 0;
for (int i = 30; i >= 0; i--)
{
int u = x >> i & 1; // 查询同理,从高位出发,找到该位时0还是1
if(son[p][!u]) // 如果存在!u这个结点,那就往这这边走
{
ans += 1 << i; // 因为在第i位出现了与该数不一样的数,异或后就变成1,
p = son[p][!u];//最后答案就是加上2的i次方
}
else p = son[p][u];
}
return ans;
}
int main()
{
scanf("%d",&n);
int res= 0;
for (int i = 0; i < n; ++i)
{
scanf("%d",&a);
insert(a);
res = max(res, query(a));
}
cout << res << endl;
return 0;
}