【数据结构】字典树(Trie树)算法总结

知识概览

  • Trie:高效地存储和查找字符串集合的数据结构
  • 数字、汉字可以用二进制位来存

例题展示

题目链接

Trie字符串统计:

https://www.acwing.com/problem/content/837/

代码

#include 

const int N = 100010;

int son[N][26], cnt[N], idx;  // 下标是0的点,既是根节点,又是空节点
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);
    while (n--)
    {
        char op[2];
        scanf("%s%s", op, str);
        if (op[0] == 'I') insert(str);
        else printf("%d\n", query(str));
    }
    
    return 0;
}

题目链接

最大异或对:

https://www.acwing.com/problem/content/145/

题解

对于每个数,先插入,然后再找和这个数异或最大的数,找的方法是找已存储在字典树的数,从高位到低位,尽量找和当前数该位不同的数。最终得到的数即为所求。

代码

#include 
#include 

using namespace std;

const int N = 100010, M = 31 * N;

int n;
int son[M][2], idx, x;

void insert(int x)
{
    int p = 0;
    for (int i = 30; i >= 0; i--)
    {
        int u = x >> i & 1;
        if (!son[p][u]) son[p][u] = ++idx;
        p = son[p][u];
    }
}

int query(int x)
{
    int p = 0, res = 0;
    for (int i = 30; i >= 0; i--)
    {
        int u = x >> i & 1;
        if (son[p][!u])
        {
            p = son[p][!u];
            res = res * 2 + !u;
        }
        else
        {
            p = son[p][u];
            res = res * 2 + u;
        }
    }
    
    return res;
}

int main()
{
    scanf("%d", &n);
    
    int res = 0;
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &x);
        insert(x);
        int t = query(x);
        res = max(res, x ^ t);
    }
    
    printf("%d\n", res);
    
    return 0;
}

你可能感兴趣的:(代码模板,数据结构,字符串,数据结构,字典树,Trie树,算法,算法与数据结构,C++)