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

Trie树专题 [转]

    1、静态建树  速度快,但可能会浪费内存  有的题用动态建树会超时,静态就不超时  
    struct trie  
    {  
        int next[maxnode][size];//小写字母size就是26,十进制就是10,二进制就是2  
        bool end[maxnode];  
        int sz;  
        trie()  
        {  
            memset(next,0,sizeof(next)); //如果值是0,就表示这个节点没有走到过  
            memset(end,false,sizeof(end));  
            sz = 0;  
        }  

        void insert(char s[])  
        {  
            int now = 0;  
            int len = strlen(s);  
            for(int i = 0; i < len; i++)  
            {  
                int index = s[i] - 'a';  
                if ( !next[now][index] ) next[now][index] = ++sz;  
                now = next[now][index];  
            }  
            end[now] = true; //在最后一个字母节点处标记  
        }  

        bool find(char s[])  
        {  
            int now = 0;  
            int len = strlen(s);  
            for(int i = 0; i < len; i++)  
            {  
                int index = s[i] - 'a';  
                if ( !next[now][index] ) return false; // 如果这个节点没有拓展过,也就不存在这个字符串  
                now = next[now][index];  
            }  
            return end[now]; //返回这个节点有没有结束标记  
        }  

    };  
    2、动态建树  速度相对慢一些,节约内存  
    struct trie  
    {  
        trie* next[size];  
        bool flag;  
    };  

    void init(trie* x)  
    {  
        x->flag = false;  
        for(int i = 0; i < size; i++) x->next[i] = NULL;  
    }  

    void insert(trie* x,char s[])  
    {  
        int len = strlen(s);  
        for(int i = 0; i < len; i++)  
        {  
            int index = s[i] - 'a';  
            if ( x->next[index] == NULL )  
            {  
                x->next[index] = new trie;  
                init(x->next[index]);  
            }  
            x = x->next[index];  
        }  
        x->flag = true;  
    }  

    bool query(trie* x,char s[])  
    {  
        int len = strlen(s);  
        for(int i = 0; i < len; i++)  
        {  
            int index = s[i] - 'a';  
            if ( x->next[index] == NULL ) return false;  
            x = x->next[index];  
        }  
        return x->flag;  
    }  

一、字符串的插入、查找

这是trie树最基础的应用,将字符串从第一个字母开始按顺序在trie树上走一遍,在最后一个字母节点处加一个结束标记。可以去查找一个字符串,也可以解决一个字符串是否为另一个字符串前缀的问题。

题目:HDU 1247

题解:http://blog.csdn.net/chy20142109/article/details/50704122

题目:POJ 2503

题解:http://blog.csdn.net/chy20142109/article/details/50704085

题目:POJ 1056

题解:http://blog.csdn.net/chy20142109/article/details/50704140

题目:POJ 3630

题解:http://blog.csdn.net/chy20142109/article/details/50704174

二、统计每个节点的访问次数

在每一个节点处加一个变量来计数,表示之前加入字符串的时候这个节点到达了多少次,也就是有多少个字符串的前缀是这个字符串。

题目:HDU 1251

题解:http://blog.csdn.net/chy20142109/article/details/50704050

题目:POJ 2001

题解:http://blog.csdn.net/chy20142109/article/details/50704221

三、解决一些带有异或计算的问题

我们可以把整数表示成二进制,把二进制状态的下值插入到字典树中进行操作。

比如:我们想在一个整数的集合中找出一个整数x,使得x和给出的一个数异或结果最大。我们考虑异或运算是按二进制位运算,相异为1,那么我们可以两个数的二进制高位尽可能的相异,就能保证答案是最大的。建trie树的时候从最高位开始往低位走,优先考虑高位,因为高位的权值大,影响大。

还有一些关于异或的小技巧,因为x^x = 0,所以当出现重复的数就会抵消。可以把这个思想运用到一些数据的处理上,现在考虑在一个区间[l,r]内,找出一段连续的数,使其异或后的结果最大/最小。我们用f[i]表示a[1]^a[2]^…^a[i],那么如果想求一段区间[x,y]的异或值就可以用f[x-1]^f[y]来表示。

回到问题,我们枚举这一段连续的数的结尾,也就是现在有一个f[i],i属于[l,r],现在想找到一个f[k],k属于[l-1,i-1],使得f[i] xor f[k]结果最大/最小。那么找f[k]的这个过程就可以用f[i]在trie树中去贪心匹配,然后对于每次枚举区间结尾计算出来的最大值更新答案。

题目:HDU 4825

题解:http://blog.csdn.net/chy20142109/article/details/50704023

题目:HDU 5269

题解:http://blog.csdn.net/chy20142109/article/details/50704324

题目:POJ 3764

题解:http://blog.csdn.net/chy20142109/article/details/50704350

题目:CodeForces 282E

题解:http://blog.csdn.net/chy20142109/article/details/50706248

相关文章:

  • using声明、using指示及其作用域详解
  • using声明、using指示用于嵌套命名空间时的作用域
  • C语言运算符优先级列表
  • 康托展开和逆康托展开
  • C语言中scanf函数的实现
  • 【codevs 1225】八数码难题
  • [codevs 1288] 埃及分数 [IDdfs 迭代加深搜索 ]
  • 浅谈一类积性函数的前缀和
  • Codeforces Round #363 (Div. 2)[B]One Bomb
  • BFS、双向BFS和A*
  • 二分的模板(花式二分)
  • STL之set集合容器
  • NOIP2016#模拟考试 Day.1# T1 洗澡
  • NOIP2016#模拟考试 Day.1# T3 导航软件
  • [hdu 4405] Aeroplane chess [概率DP 期望]
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • angular2开源库收集
  • ERLANG 网工修炼笔记 ---- UDP
  • If…else
  • Java多线程(4):使用线程池执行定时任务
  • JS实现简单的MVC模式开发小游戏
  • k个最大的数及变种小结
  • Linux后台研发超实用命令总结
  • NSTimer学习笔记
  • open-falcon 开发笔记(一):从零开始搭建虚拟服务器和监测环境
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • RxJS: 简单入门
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • vue的全局变量和全局拦截请求器
  • 我建了一个叫Hello World的项目
  • 新书推荐|Windows黑客编程技术详解
  • 学习使用ExpressJS 4.0中的新Router
  •  一套莫尔斯电报听写、翻译系统
  • 异步
  • 在weex里面使用chart图表
  • #《AI中文版》V3 第 1 章 概述
  • #图像处理
  • $.ajax中的eval及dataType
  • (14)Hive调优——合并小文件
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (循环依赖问题)学习spring的第九天
  • (转)winform之ListView
  • . NET自动找可写目录
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .net连接oracle数据库
  • /usr/bin/env: node: No such file or directory
  • @RestController注解的使用
  • [383] 赎金信 js
  • [Angular] 笔记 9:list/detail 页面以及@Output
  • [BZOJ4010]菜肴制作