当前位置: 首页 > news >正文

字典树(Trie)——入门篇

字典树

Trie(字典树)又称前缀树

给出字符串集合:code、cook、five、file、fat,我们设根节点为空节点,那么其Trie树如下所示:
在这里插入图片描述

字典树又称前缀树,给出一个字符串集合,我们可以通过公共前缀将整个字符串集合存到一个树形结构中,一旦形成了集合中的字符串,我们只需在树上的相应节点打上标记

存储

我们采用双数组存储的方式,其中Next数组是二维数组,第二维之所以是26是因为每个节点都可能连接26个字母,另外一个标记数组可以有两种形式:

  • bool类型的vis数组只标记该节点结尾字符串是否存在
  • int类型的num数组既可以标记是否存在又能存储在集合中的下标
const int maxn=max_len*num;   //字符串最大长度乘以数量
int Next[maxn][26];
bool vis[maxn];     //该结点结尾的字符串是否存在
int num[maxn];	    //该结点结尾的字符串是否存在,存在则保存下标

不难发现我们在存储时是将字符转化为0-25的数字下标:
在这里插入图片描述

建树

如何建树?我们采用动态开点的方式,这里类似链式前向星那样。Next数组第一维保存的就是动态开点的数,第二维是接下来指向的字符(0-25)

每个字符串的第一个字符保存在下标为0的集合中,而且root实际上是不存在的,也就是说如果有多种字母开头的字典树,那么这实际上是一个森林

建树的过程即插入的过程,时间复杂度为O(n*len)

标记是否存在

int cnt=0;
void insert(char *s) {    //插入字符串
        int p=0,len=strlen(s);
        for(int i=0;i<len;i++){
            int c=s[i]-'a';
            if(!Next[p][c]) Next[p][c]=++cnt;  //没有就添加结点
            p=Next[p][c];
        }
        vis[p]=1;
    }

标记并保存下标

int cnt=0;
void insert(char *s,int k) {  //插入字符串集合的字符串k
        int p=0,len=strlen(s);
        for(int i=0;i<len;i++){
            int c=s[i]-'a';
            if(!Next[p][c]) Next[p][c]=++cnt;  //没有就添加结点
            p=Next[p][c];
        }
        num[p]=k;
    }

查找字符串

查找时,首先目标串的每一个前缀必须都出现,也就是Next[p][s[i]-‘a’]都有值,那么查询到最后一个节点时,如果该节点被标记,那么vis[p]就不为0,否则为0,因此直接返回vis[p]

查询的时间复杂度为O(len)

int find(char *s){      //查找字符串
        int p=0,len=strlen(s);
        for(int i=0;i<len;i++){
            int c=s[i]-'a';
            if(!Next[p][c]) return 0;
            p=Next[p][c];
        }
        return vis[p];
    }

简单模板

const int maxn=max_len*num; //每个字符串最大长度乘以字符串数量
struct Trie{
    int Next[maxn][26],cnt;
    bool vis[maxn];           //该结点结尾的字符串是否存在
    //int num[maxn];

    void init(){
        cnt=0;
        memset(vis,0,sizeof vis);
        memset(Next,0,sizeof Next);
    }

    void insert(char *s,int k) {    //插入字符串
        int p=0,len=strlen(s);
        for(int i=0;i<len;i++){
            int c=s[i]-'a';
            if(!Next[p][c]) Next[p][c]=++cnt;  //没有就添加结点
            p=Next[p][c];
        }
        vis[p]=1;
    }

    int find(char *s){    // 查找字符串
        int p=0,len=strlen(s);
        for(int i=0;i<len;i++){
            int c=s[i]-'a';
            if(!Next[p][c]) return 0;
            p=Next[p][c];
        }
        return vis[p];
    }
};

相关文章:

  • 警惕:电信加紧发力为哪般?(下)
  • Codeforces Round #637 (Div. 2) C. Nastya and Strange Generator(阅读理解/思维)
  • Broken Space Bar(Trie)[待补]
  • 小白兔和小灰兔
  • VC图片显示特效
  • UVA1153 Keep the Customer Satisfied(贪心+优先队列)
  • UVA10570 Meeting with Aliens(枚举/优化)
  • flash小实验
  • 2019 ICPC Greater New York Region J - Unicycles (规律+递推+矩阵快速幂)
  • WebLogic 9.2中文帮助网站公测中,欢迎大家访问!
  • 2019 ICPC Greater New York Region C - PassTheBuck(概率)
  • Oracle11gR2安装简介
  • 2019 ICPC Greater New York Region I - RationalBase(思维+进制转换)
  • 广告营销的创新
  • Educational Codeforces Round 86 C - Yet Another Counting Problem(规律+前缀和)
  • 30秒的PHP代码片段(1)数组 - Array
  • C++11: atomic 头文件
  • Java程序员幽默爆笑锦集
  • oldjun 检测网站的经验
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • spark本地环境的搭建到运行第一个spark程序
  • Spring Boot快速入门(一):Hello Spring Boot
  • spring security oauth2 password授权模式
  • Theano - 导数
  • 初识 beanstalkd
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 一、python与pycharm的安装
  • 一道闭包题引发的思考
  • nb
  • 06-01 点餐小程序前台界面搭建
  • 进程与线程(三)——进程/线程间通信
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • $$$$GB2312-80区位编码表$$$$
  • $.ajax()
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (HAL库版)freeRTOS移植STMF103
  • (zhuan) 一些RL的文献(及笔记)
  • (附源码)php投票系统 毕业设计 121500
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (一一四)第九章编程练习
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • ****Linux下Mysql的安装和配置
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • .net framework4与其client profile版本的区别
  • .Net Remoting常用部署结构
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • /etc/sudoer文件配置简析
  • @Autowired和@Resource装配
  • @param注解什么意思_9000字,通俗易懂的讲解下Java注解
  • [ Linux ] Linux信号概述 信号的产生
  • [ 蓝桥杯Web真题 ]-Markdown 文档解析
  • [20180129]bash显示path环境变量.txt