字典树及其应用

浅析字典树

字典树是一种比较特殊的树,边上有边权(至少我是怎么理解的)。又名“Trie”树。

大概长这样:

1hwGtI.png

(插入了cap,cat,csp,co,code)

边上是字符集,点上是点的编号,涂成蓝色的代表是单词的结尾。

字符集可以是a-z0-9true和false等等。

字典树有效的组织了单词的关系,节省了时间和空间。

插入单词

void insert(char *s) {
    int p = 1, len = strlen(s);
    for (int i = 0; i < len; ++i) {
        bool now = s[i] - 'a';
        if (trie[p][now] == 0) trie[p][now] = ++m;
        p = trie[p][now];
    }
    isend[p] = true;
}

这里trie[x][c]表示从节点xc这条边能达到节点trie[x][c]

其中,m为节点总数计数,要在插入前赋初始值为 1

这里isend用于标记是否是结尾,有时还需要记录次数。

查询

每道题都有他查询的内容,需要因地制宜的写查询函数。

查询前缀是否出现:

bool query(char *s) { // 此代码没有编译运行测试过,仅供思路参考,不建议直接复制。
    int p = 1, len = strlen(s);
    for (int i = 0; i < len; ++i) {
        bool now = s[i] - 'a';
        if (trie[p][now] == 0) return false;
        p = trie[p][now];
    }
    return true;
}

查询出现次数(注意配套修改insert函数):

int query(char *s) { // 此代码没有编译运行测试过,仅供思路参考,不建议直接复制。
    int p = 1, len = strlen(s);
    for (int i = 0; i < len; ++i) {
        bool now = s[i] - 'a';
        if (trie[p][now] == 0) return 0;
        p = trie[p][now];
    }
    return isend[p];
}

应用

本文主要谈应用字典树解题,如果上面的讲解不明白,可以自行Baidu一下qwq。

例题一 于是他错误的点名开始了

查看原题-洛谷P2580

这题是字典树最基本的运用,查询存在性和重复性。

把所有化学生的姓名插入字典树,再在每次教练点名时,查询。

例题二 The XOR Largest Pair

查看原题-LibreOJ#10050

这题看似和字典树没啥关系,也找不到可以插入的字符串。

最容易想到的做法就是暴力,两两枚举xor,时间复杂度 O(n2)

其实这里可以把每个数的二进制值插入字典树中,

枚举每个数,在字典树中查询与它尽量二进制按位尽量相反的树。

code:

void insert(int x) {
    int p = 1;
    for (int i = 30; i >= 0; --i) {
        bool now = (x & (1 << i));
        if (trie[p][now] == 0) trie[p][now] = ++m;
        p = trie[p][now];
    }
    isend[p] = true;
}

int lookup(int x) {
    int res = 0;
    int p = 1;
    for (int i = 30; i >= 0; --i) {
        bool now = (x & (1 << i));
        now = !now;
        if (trie[p][now]) { // 成功匹配,此位相反
            res |= (1 << i);
            p = trie[p][now];
        } else { // 匹配失败,这一位只能相等
            p = trie[p][!now];
        }
    }
    return res;
}

例题三 最长XOR序列

查看题目-暂无题目qwq

描述:还是给你一个序列,要求这个序列的某个子序列的异或和最大,求这个最大值。

(注:子序列是连续的,子串才是不连续的。

异或和是指连续异或的值,如4,7,10的异或和是4 xor 7 xor 10

这里要用到异或的几个性质:

  1. axorbxorc=(axorb)xorc=axor(bxorc)

  2. axora=0

  3. axor0=a

posted @   方而静  阅读(278)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示