Trie,又经常叫前缀树,字典树等等。它有很多变种,如后缀树,Radix Tree/Trie,PATRICIA tree,以及bitwise版本的crit-bit tree。当然很多名字的意义其实有交叉。


定义

在计算机科学中,trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。

trie中的键通常是字符串,但也可以是其它的结构。trie的算法可以很容易地修改为处理其它结构的有序序列,比如一串数字或者形状的排列。比如,bitwise trie中的键是一串位元,可以用于表示整数或者内存地址


基本性质

1.根节点不包含字符,除根节点意外每个节点只包含一个字符。

2.从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。

3.每个节点的所有子节点包含的字符串不相同。


优点:

可以最大限度地减少无谓的字符串比较,故可以用于词频统计和大量字符串排序。

缺点: 虽然不同单词共享前缀,但其实trie是一个以空间换时间的算法。其每一个字符都可能包含至多字符集大小数目的指针(不包含卫星数据)。

应用场景:

(1) 字符串检索 事先将已知的一些字符串(字典)的有关信息保存到trie树里,查找另外一些未知字符串是否出现过或者出现频率。

1000万字符串,其中有些是重复的,需要把重复的全部去掉,保留没有重复的字符串。

(2)文本预测、自动完成,see also,拼写检查

(3)词频统计

若无内存限制:Trie + “k-大/小根堆”(k为要找到的数目)。

否则,先hash分段再对每一个段用hash(另一个hash函数)统计词频,再要么利用归并排序的某些特性(如partial_sort),要么利用某使用外存的方法。

(4)排序

Trie树是一棵多叉树,只要先序遍历整棵树,输出相应的字符串便是按字典序排序的结果。 比如给你N 个互不相同的仅由一个单词构成的英文名,让你将它们按字典序从小到大排序输出。

(5)字符串最长公共前缀

Trie树利用多个字符串的公共前缀来节省存储空间,当我们把大量字符串存储到一棵trie树上时,我们可以快速得到某些字符串的公共前缀。

eg: 给出N 个小写英文字母串,以及Q 个询问,即询问某两个串的最长公共前缀的长度是多少?

解决方案:首先对所有的串建立其对应的字母树。此时发现,对于两个串的最长公共前缀的长度即它们所在结点的公共祖先个数,于是,问题就转化为了离线(Offline)的最近公共祖先(Least Common Ancestor,简称LCA)问题。 而最近公共祖先问题同样是一个经典问题,可以用下面几种方法:

  • 利用并查集(Disjoint Set),可以采用采用经典的Tarjan 算法;
  • 求出字母树的欧拉序列(Euler Sequence )后,就可以转为经典的最小值查询(Range Minimum Query,简称RMQ)问题了;

(6)字符串搜索的前缀匹配

trie树常用于搜索提示。如当输入一个网址,可以自动搜索出可能的选择。当没有完全匹配的搜索结果,可以返回前缀最相似的可能。 Trie树检索的时间复杂度可以做到n,n是要检索单词的长度, 如果使用暴力检索,需要指数级O(n^2)的时间复杂度。

(7) 作为其他数据结构和算法的辅助结构

如后缀树,AC自动机等(后缀树可以用于全文搜索


模板

题目

#include <cstdio>
#include <cstring>
using namespace std; const int MAXN = 1e6 + 5;
int cnt = 1, Trie[MAXN][26];
int End[MAXN]; void Insert(char s[], int len) {
int p = 1;
for(int i = 0; i < len; i++) {
int ch = s[i] - 'a';
if(Trie[p][ch] == 0)
Trie[p][ch] = ++cnt;
p = Trie[p][ch];
}
End[p]++;
} int search(char s[], int len) {
int p = 1;
for(int i = 0; i < len; i++) {
int ch = s[i] - 'a';
p = Trie[p][ch];
if(!p)
return false;
}
return End[p];
} char st[MAXN], ask[MAXN];
int main() {
int n, m;
scanf ("%d %d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf ("%s", st);
Insert(st, strlen(st));
}
for(int i = 1; i <= m; i++) {
scanf ("%s", st);
int len = 0, ans = 0;
for(int j = 1; j <= strlen(st); j++)
ans += search(st, j);
printf("%d\n", ans);
}
return 0;
}

Trie树总结的更多相关文章

  1. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  2. 基于trie树的具有联想功能的文本编辑器

    之前的软件设计与开发实践课程中,自己构思的大作业题目.做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改.github:https://github.com/chu ...

  3. hihocoder-1014 Trie树

    hihocoder 1014 : Trie树 link: https://hihocoder.com/problemset/problem/1014 题意: 实现Trie树,实现对单词的快速统计. # ...

  4. 洛谷P2412 查单词 [trie树 RMQ]

    题目背景 滚粗了的HansBug在收拾旧英语书,然而他发现了什么奇妙的东西. 题目描述 udp2.T3如果遇到相同的字符串,输出后面的 蒟蒻HansBug在一本英语书里面找到了一个单词表,包含N个单词 ...

  5. 通过trie树实现单词自动补全

    /** * 实现单词补全功能 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #incl ...

  6. #1014 Trie树

    本题主要是求构造一棵Trie树,即词典树用于统计单词. C#代码如下: using System; using System.Collections.Generic; using System.Lin ...

  7. Trie树-字典查找

    描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一本词典,于是小Hi就向小Ho提出了那个经典的问题: ...

  8. Trie树的创建、插入、查询的实现

    原文:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=28977986&id=3807947 1.什么是Trie树 Tr ...

  9. Trie树(c++实现)

    转:http://www.cnblogs.com/kaituorensheng/p/3602155.html http://blog.csdn.net/insistgogo/article/detai ...

  10. [转]双数组TRIE树原理

    原文名称: An Efficient Digital Search Algorithm by Using a Double-Array Structure 作者: JUN-ICHI AOE 译文: 使 ...

随机推荐

  1. OpenCV412+contrib+CUDA+cuDNN

    首先现在好软件(包含源码和官方编译好的库)和contrib源码包(对应版本怎么下载????) 软件: contirb包: 1.先把软件解压,在目录新建mybuild文件夹,用于输出保存自定义VS工程 ...

  2. 使用MQTT协议的4G DTU模块具有什么优势

    什么是MQTT协议 要了解使用MQTT协议的4G DTU模块具有哪些优势,首先我们需要了解什么是MQTT协议,MQTT协议最早是IBM开发的一个即时通讯协议,它的主要是为大量计算能力有限且工作在低带宽 ...

  3. python中的 异常处理(try...expect)

    错误处理 关注公众号"轻松学编程"了解更多. 在程序运行的过程中,如果发生了错误,可以事先约定一个错误代码,这样就可以知道是否有错,以及出错的原因,在操作系统的调用中,返回错误码的 ...

  4. C#编译时与运行时

    曾几何时,对C#编译时与运行时的理解总是不是那么明显.以下对此部分说明一下自己的理解. 定义 编译时 将C#程序编译成中间代码的过程.其过程是对程序进行词法分析,语法分析等. 运行时 就是程序最终分配 ...

  5. CF1320C World of Darkraft: Battle for Azathoth

    线段树 又是熟悉的感觉,又是E题写完了,没调完,不过还好上了紫 CF1295E 可以发现可以打败怪兽的关系类似二维偏序 那么首先考虑第一维(武器)以攻击值($a_{i}$)进行排序 把所有的怪兽以防御 ...

  6. dat.GUI 打造可视化工具(一)

    前言 有时候学习api其实我们可以从源码的角度学习,因为有时候很多文档写的太不清楚了,自己都是慢慢去试,去猜,去实现其实也是挺浪费时间的,面对未知的一脸蒙蔽,偶尔烦躁,其实需要的是自己静下心来慢慢研究 ...

  7. HTML+JavaScript实现一个简单抽奖功能

    为什么会做这个东西呢,纯属好玩,闲的其实是在上次班会的时候想到的,班会的时候叫人回答问题,没人回答当时就想,我如果抽签抽到你了,你还是不回答吗??好吧,一切都是扯淡先来看看页面效果吧:点击抽取就可以抽 ...

  8. javascript-闭包【面试必备】

    闭包 定义:内层函数可以访问外层函数作用域的变量 意义/用途: 1.封装细节 2.实现模块化 3.常用实战li列表 // querySelectorAll es5支持的一个类似于jq的复杂选择器选取d ...

  9. link和@import引入css 区别,不建议使用@import

    众多周知,有两种方法可以在页面中导入样式文件. <link href="a.css" rel="stylesheet"> <style> ...

  10. PHP-Parse 简介以及在 Hyperf 中的应用

    介绍 PHP-Parse 是分析 PHP 代码生成 AST 的库,分析出可读性很高的对象数据结构,方便后续的更新和遍历. PHP-Parse 的主要作用是修改原有代码(比如插入自定义的代码片段),生成 ...