• Trie树简单讲解


    字典树(Trie Tree)

    trie树就是用来对于大量的文本统计,储存与查找的一种数据结构,下面简单介绍两种trie树的实现方式。


    • 多叉trie树

    对于一个字符集大小为S的文本,我们可以建立一棵S叉树,将文本统计。

    具体实现如下:

    首先我们对于一个节点,开一个大小为S的数组,来表示它对于的子节点。比如对于小写字母的字符集,大小为26,我们就可以定义如下的节点:(我们将a~z重新编号为0~25)

    struct node{
        int son[26];
        int flag;
    };

    其中son[i],表示当前这个节点下一个字母编号为i所对应的节点的编号,我们是将字母放在边上的。

    所以对于一个字符串,我们可以用O(len)的时间插入到trie树中,len为字符串长度。

    int tot;//表示节点个数
    node trie[N];/trie树节点
    int getid(char c){return c-'a';}
    //获取字符编号
    void insert(char *s,int len){
        int nowid=0;//当前的节点编号,这里我们把0号点当做根节点。
        for(int i=0,j;i<len;i++){
            j=getid(s[i]);//获取当前的字符编号
            if(!trie[nowid].son[j])
                trie[nowid].son[j]=++tot;//如果没有该结点,那么就将新建一个节点,节点个数增加。
            nowid=trie[nowid].son[j];
            //走到下一个节点。
        }
        trie[nowid].flag++;
        //将结束位置做上标记,表示有一个字符串在这里结束。
    }
    

    而我们发现,当字符集很大时,空间复杂度最坏是len×S的,所以有没有更好的方法呢?下面就来介绍第二种。

    • 链表式trie树(时间换空间法)

    我们可以像建图一样,将trie树建出,而没出现的节点就可以不用建,那么将大大节省空间复杂度,但是也有坏处就是我们不能O(1)的查找某一个节点对应的下一个某个字母的节点编号,而是需要去遍历所以的子节点,但是有时候时间换空间是明智的。

    具体实现是类似的,但是在这里我们就不定义节点,可以定义一个边,如下:

    struct side{
        int to,next;
        char c;//记录每条边对应的字符
    };
    int head[M],cnt;
    //to表示下一个节点的编号和next表示链表的指针。
    //head表示链表的表头,cnt记录边数
    

    那么增加一条边就简单了:

    side g[N];
    void add(int a,int b,char c){
        g[++cnt]=(side){b,head[a],c};head[a]=cnt;
    }

    然后插入一个字符串的方式同第一种,只是细节变化了一点。

    int flag[N];//记录节点标记
    int tot;//表示节点个数
    void insert(char *s,int len){
        int nowid=0,pos;//同样的0为根节点,pos记录下一个边的编号。
        for(int i=0;i<len;i++){
            for(pos=head[nowid];pos;pos=g[e].next){
                if(g[pos].c==s[i])break;
            }//去寻找下一个节点的编号
            if(!pos){
                add(nowid,++tot,s[i]);
                pos=cnt;
            }
            nowid=g[pos].to;
        }
        flag[nowid]++;
    }
    

    这就是两种trie树的方法啦!QAQ有错请指出


    例题:


    应用技巧:

    其实trie树大多都是运用在AC自动机上面,然后夹杂一些其他的例如DP之类的。

    trie树的特殊应用:可以来求异或最大值,方法就是将所有数字转换成二进制插入trie树,这时的trie树就变成了一个二叉树,然后异或最大就按照高位到低位贪心的在trie树上找一遍就好了。

    下面附上一个AC自动机学习和trie树学习的神器

    Go To Download密码xbj6

  • 相关阅读:
    Atom,AtomPub 和Java 转载
    使用OData协议查询Windows日志 转
    许可协议BSD GPL MPL LGPL APL转载
    Eclipse Galileo 简介
    常见证书格式和转换
    JVM简介转
    Android Native 代码开发学习笔记转载
    echarts——各个配置项详细说明总结
    Mysql 安装服务无法启动解决方案与使用的一般使用指令
    js中如何把字符串(文本)转化为对象
  • 原文地址:https://www.cnblogs.com/VictoryCzt/p/10053435.html
Copyright © 2020-2023  润新知