当前位置: 首页 > 编程日记 > 正文

trie树 详解

前几天学习了并查集和trie树,这里总结一下trie。
    本文讨论一棵最简单的trie树,基于英文26个字母组成的字符串,讨论插入字符串、判断前缀是否存在、查找字符串等基本操作;至于trie树的删除单个节点实在是少见,故在此不做详解。

l        Trie原理

Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。

l        Trie性质

好多人说trie的根节点不包含任何字符信息,我所习惯的trie根节点却是包含信息的,而且认为这样也方便,下面说一下它的性质 (基于本文所讨论的简单trie树)

1.    字符的种数决定每个节点的出度,即branch数组(空间换时间思想)

2.    branch数组的下标代表字符相对于a的相对位置

3.    采用标记的方法确定是否为字符串。

4.    插入、查找的复杂度均为O(len),len为字符串长度

l        Trie的示意图

如图所示,该trie树存有abc、d、da、dda四个字符串,如果是字符串会在节点的尾部进行标记。没有后续字符的branch分支指向NULL





l        
Trie
Trie的优点举例

已知n个由小写字母构成的平均长度为10的单词,判断其中是否存在某个串为另一个串的前缀子串。下面对比3种方法:

1.    最容易想到的:即从字符串集中从头往后搜,看每个字符串是否为字符串集中某个字符串的前缀,复杂度为O(n^2)。

2.    使用hash:我们用hash存下所有字符串的所有的前缀子串。建立存有子串hash的复杂度为O(n*len)。查询的复杂度为O(n)* O(1)= O(n)。

3.    使用trie:因为当查询如字符串abc是否为某个字符串的前缀时,显然以b,c,d....等不是以a开头的字符串就不用查找了。所以建立trie的复杂度为O(n*len),而建立+查询在trie中是可以同时执行的,建立的过程也就可以成为查询的过程,hash就不能实现这个功能。所以总的复杂度为O(n*len),实际查询的复杂度只是O(len)。


解释一下hash为什么不能将建立与查询同时执行,例如有串:911,911456输入,如果要同时执行建立与查询,过程就是查询911,没有,然后存入9、91、911,查询911456,没有然后存入9114、91145、911456,而程序没有记忆功能,并不知道911在输入数据中出现过。所以用hash必须先存入所有子串,然后for循环查询。

而trie树便可以,存入911后,已经记录911为出现的字符串,在存入911456的过程中就能发现而输出答案;倒过来亦可以,先存入911456,在存入911时,当指针指向最后一个1时,程序会发现这个1已经存在,说明911必定是某个字符串的前缀,该思想是我在做pku上的3630中发现的,详见本文配套的“入门练习”。

l        Trie的简单实现(插入、查询)

View Code

 
#include <iostream>
using namespace std;
const int branchNum = 26//声明常量 
int i;

struct Trie_node
{
    bool isStr; //记录此处是否构成一个串。
    Trie_node *next[branchNum];//指向各个子树的指针,下标0-25代表26字符
    Trie_node():isStr(false)
    {
        memset(next,NULL,sizeof(next));
    }
};

class Trie
{
public:
    Trie();
    void insert(const char* word);
    bool search(char* word); 
    void deleteTrie(Trie_node *root);
private:
   Trie_node* root;
};

Trie::Trie()
{
    root = new Trie_node();
}
void Trie::insert(const char* word)
{
    Trie_node *location = root;
    while(*word)
    {
        if(location->next[*word-'a'] == NULL)//不存在则建立
        {
            Trie_node *tmp = new Trie_node();
            location->next[*word-'a'] = tmp;
        }    
        location = location->next[*word-'a']; //每插入一步,相当于有一个新串经过,指针要向下移动
        word++;
    }
    location->isStr = true//到达尾部,标记一个串
}

bool Trie::search(char *word)
{
    Trie_node *location = root;
    while(*word && location)
    {
        location = location->next[*word-'a'];
        word++;
    }
    return(location!=NULL && location->isStr);
}

void Trie::deleteTrie(Trie_node *root)
{
    for(i = 0; i < branchNum; i++)
    {
        if(root->next[i] != NULL)
        {
            deleteTrie(root->next[i]);
        }
    }
    delete root;
}

void main() //简单测试
{
    Trie t;
    t.insert("a");         
    t.insert("abandon");
    char * c = "abandoned";
    t.insert(c);
    t.insert("abashed");
    if(t.search("abashed"))
        printf("true\n");

本文转载自:http://www.cnblogs.com/cherish_yimi/archive/2009/10/12/1581666.html

转载于:https://www.cnblogs.com/xufeiyang/articles/2469632.html

相关文章:

启动hadoop的节点

1.启动hadoop的节点 start-dfs.sh 本文转自 素颜猪 51CTO博客&#xff0c;原文链接:http://blog.51cto.com/suyanzhu/1959242

什么是Python线程?Python线程如何创建?

相信正在学习Python技术或者对Python语言有一定了解的人对于Python线程应该都不陌生&#xff0c;但是也有刚接触Python的小伙伴对于Python线程并不了解&#xff0c;今天小编就跟大家聊聊什么是Python线程&#xff0c;又该如何创建Python线程! 什么是Python线程?Python线程如何…

ItemAdding实现数据验证--中文字段,properties.AfterProperties值为null的问题

最近写事件接收器&#xff0c;发现中文字段如果直接用properties.AfterProperties[“申请人"]这样获取的值为null&#xff0c;无法得到值。后拉忽然发现用英文字段可以得到值。难道中文字段需要编码&#xff1f;经过测试果真如此。 代码部分如下&#xff1a;public overri…

jstl c:choose、c:when和c:otherwise标签

在用spring mvc中&#xff0c;页面前端老用jstl&#xff0c;记录一下。 <c:choose>、<c:when>和<c:otherwise>在一起连用&#xff0c;可以实现Java语言中的if-else语句的功能。例如以下代码根据username请求参数的值来打印不同的结果&#xff1a; <c:choo…

怎样设计出优秀的测试用例?看看下面就知道了

想要成为一名合格的软件测试工程师&#xff0c;一份合格软件测试报告是非常重要的&#xff0c;软件测试的核心也就是测试的用例了&#xff0c;我们通过用例可以看出怎么设计出来可以发现问题&#xff0c;可以有效的覆盖需求的&#xff0c;没有冗余的用例是每个测试工程师必须跨…

数据结构与算法:12 数组与稀疏矩阵

12 数组与稀疏矩阵 知识结构&#xff1a; 1. 数组 1.1 数组的定义 数组是具有一定顺序关系的若干对象组成的集合&#xff0c;组成数组的对象称为数组元素。 例如&#xff1a; 向量对应一维数组 A(a0,a1,⋯,an−1)A(a_0,a_1,\cdots,a_{n-1}) A(a0​,a1​,⋯,an−1​) 矩阵…

管理索引表:深入研究B树索引--重建,合并,删除(理论篇3)

重建索引  如果表中记录频繁地被删除或插入&#xff0c;尽管表中的记录总量保持不变&#xff0c;索引空间的使用量会不断增加。虽然记录从索引中被删除&#xff0c;但是该记录索引项的使用空间不能被重新使用。因此&#xff0c;如果表变化不定&#xff0c;索引空间量会不断增…

模块架构不是软件成功的“决定因素”

【本文是09年的一篇旧文&#xff0c;出于某些原因&#xff0c;对原文内容有删减&#xff0c;在这里整理后重新发表】 前言感谢XXX对我们技术&#xff0c;对我们公司产品提出这些意见&#xff0c;我们公司卖的是软件产品&#xff0c;开发软件是一件技术活&#xff0c;说实话&…

JavaScript面向对象修改标签页详解

双击标签页组件中的li小标签或者section 中的文本&#xff0c;可以对文本进行编辑。为了实现这个功能&#xff0c;需要先给li和section元素绑定双击事件&#xff0c;当双击文本后&#xff0c;将文本改成一个文本框&#xff0c;用来输入新的内容&#xff0c;在文本框中显示原来的…

数据结构与算法:13 字符串与整数集合

13 字符串与整数集合 知识点&#xff1a; 1. 字符串 我们古人没有电影电视&#xff0c;没有游戏网络&#xff0c;所以文人们就会想出一些文字游戏来娱乐。比如宋代的李禺写了这样一首诗&#xff1a;“枯眼望遥山隔水&#xff0c;往来曾见几心知&#xff1f;壶空怕酌一杯酒&am…

是时候开始使用JavaScript严格模式了怎样启用javascri

E是时候开始使用JavaScript严格模式了怎样启用javascriCMAScript5将严格模式(strictmode)引入了Javascript中&#xff0c;目的是允许开发人员能够选择“更好”的Javascript版本&#xff0c;这个版本能用不同的方式处理那些普遍而又臭名昭著的错误。一开始的时候&#xff0c;我对…

Linux服务器日志备份到本地

1、确定线上服务器的日志文件名称和路径 2、一台本地服务器能连接公网&#xff0c;创建一个日志账户&#xff0c;设置密码 3、线上服务器要求&#xff1a; a、确定是否已安装sshpass包 [rootiZwz9ghdadtaey1msor7gnZ sh]# rpm -qa|grep sshpass sshpass-1.06-1.el7.x86_64 如不…

学习UI设计能做什么

UI设计这个岗位对于目前的很多企业来说是供不应求的&#xff0c;很多刚培训完UI设计的小伙伴&#xff0c;都不知道该如何定位自己的职能岗&#xff0c;那么学习UI设计能做什么呢?来看看下面小编的详细介绍就知道了。 学习UI设计能做什么? 1、图形设计/界面设计 软件产品的产品…

数据结构与算法:14 Leetcode同步练习(五)

Leetcode同步练习&#xff08;五&#xff09; 目录 题目01&#xff1a;用栈实现队列题目02&#xff1a;托普利茨矩阵题目03&#xff1a;罗马数字转整数题目04&#xff1a;最长公共前缀题目05&#xff1a;反转字符串题目06&#xff1a;无重复字符的最长子串题目07&#xff1a;…

Oracle Spatial构建自定义投影坐标系

之前项目换过服务器&#xff0c;移植数据库时候并没有正确完整的移植自定义的投影坐标系&#xff0c;结果就报出莫名其妙的一些错误&#xff0c;比如unable to transform rectangle due to: ORA-13199: SRID does not exist。 因为在移植坐标系的时候仅仅只是将MDSYS.SDO_CRS_C…

php.ini 中开启短标签

控制参数&#xff1a; short_open_tag On如果设置为Off&#xff0c;则不能正常解析类似于这样形式的php文件&#xff1a;<?phpinfo()?>而只能解析<?phpphpinfo()?>这样形式的php文件所以要想php支持短标签&#xff0c;需要我们把short_open_tag 设置为On. 本…

参加UI培训就业多长时间

​ UI设计在近几年的发展前景是非常好的&#xff0c;越来越多的人都想要学习UI设计&#xff0c;目前大家比较想了解的是参加UI培训就业多长时间?来看看下面的详细介绍。 参加UI培训就业多长时间? 如今市面上的UI设计培训机构很多&#xff0c;选择一个口碑好靠谱的培训机构学习…

数据结构与算法:15 树

15 树 知识结构&#xff1a; 1. 树的基本概念与术语 1.1 树的定义 树是N(N≥0)N(N \geq 0)N(N≥0)个结点组成的有穷集合 &#xff0c;该集合具有如下特征&#xff1a; &#xff08;1&#xff09;除N0N0N0的树外&#xff0c;有且仅有一个特定的称为根的结点。 &#xff08;…

【as3】键盘事件

在AS3中&#xff0c;键盘事件是由KeyboardEvent类来处理的&#xff0c;属于flash.events包里面&#xff0c;有两种类型的键盘事件&#xff1a;KeyboardEvent.KEY_DOWN 和 KeyboardEvent.KEY_UP&#xff0c;对于键的代码获得我们通过keyCode这个属性 其实键盘事件使用起来还是相…

在后台代码中引入XAML的方法

本文将介绍三种方法用于在后台代码中动态加载XAML&#xff0c;其中有两种方法是加载已存在的XAML文件&#xff0c;一种方法是将包含XAML代码的字符串转换为WPF的对象。 这些是我在编写RegeX时获得的经验&#xff0c;它们将会给WPF程序带来更多的灵活性。 一、在资源字典中载入项…

JavaScript面向对象怎样删除标签页?

单击小标签右上角的按钮可D头删除标签页。其开发思路是&#xff0c;为“x”元素绑定单击事件&#xff0c;事件触发后&#xff0c;通过父元素1i获取索弓引值&#xff0c;然后用这个索引值将对应的li和section删除&#xff0c;并在删除后更新标签页的选中效电下面我们们就开始进行…

数据结构与算法:16 Leetcode同步练习(六)

Leetcode同步练习&#xff08;六&#xff09; 目录 题目01&#xff1a;相同的树题目02&#xff1a;对称二叉树题目03&#xff1a;二叉树的最大深度题目04&#xff1a; Pow(x, n)题目05&#xff1a;子集题目06&#xff1a;格雷编码题目07&#xff1a;二叉树的最近公共祖先题目…

Apache启动时报Could not reliably determine the server's fully qualified domain name

在系统启动时apache&#xff0c;没有启动起来&#xff0c;查看“事件查看器”发现报一些错误&#xff1a; The Apache service named reported the following error:>>> httpd.exe: Could not reliably determine the servers fully qualified domain name, using 19…

Windows Phone SDK update for Windows Phone 7.8

下载&#xff1a;http://www.microsoft.com/en-us/download/details.aspx?id36474 (在线安装) http://kuai.xunlei.com/d/cHbJCAIX4wBNVgFR5aa (离线下载 全语言 5.5G....) MS博客介绍&#xff1a;http://blogs.windows.com/windows_phone/b/wpdev/archive/2013/01/22/now-a…

作为一名合格的前端开发工程师需要会哪些

作为一名合格的前端开发工程师需要会哪些?web前端要学习的内容有很多&#xff0c;想要成为一名合格的web前端工程师&#xff0c;综合实力是要非常强的&#xff0c;来看看下面的详细介绍吧。 作为一名合格的前端开发工程师需要会哪些?前端开发工程师不仅要掌握基本的前端开发技…

memcached部署

第1章 memcached 1 memcached前言 1.1 memcached诞生的原因 2003年诞生了memcached Web1.0 2005以前 企业提供内容为主。 Web2.02005-2012 企业只提供平台&#xff0c;用户参与上传下载内容。 memcached 内存缓存软件&#xff0c;内存比磁盘快。 传统场景中&#xff0c;多数…

线性代数:第二章 矩阵及其运算

本讲义是自己上课所用幻灯片&#xff0c;里面没有详细的推导过程&#xff08;笔者板书推导&#xff09;只以大纲的方式来展示课上的内容&#xff0c;以方便大家下来复习。 本章主要介绍有关矩阵的知识&#xff0c;主要包括矩阵的基本运算&#xff08;加法、数乘、乘法、乘幂、…

sdut 2401 最大矩形面积

1http://acm.sdut.edu.cn/sdutoj/problem.php?actionshowproblem&problemid2401 /*2 最大矩形面积&#xff0c;把边界点加上3 从左往右 处理一遍&#xff1b;4 再从上往下处理一遍&#xff1b;5 */6 7 #include<stdio.h>8 #define maxn 200009 #include<cmath>…

Python中怎样改变集合之间的关系?

Python中怎样改变集合之间的关系?数学中&#xff0c;两个集合关系的常见操作包括&#xff1a;交集、并集、差集、补集。设A&#xff0c;B是两个集合&#xff0c;集合关系的操作介绍如下&#xff1a; 交集是指属于集合A且属于集合B的元素所组成的集合&#xff0c; 并集是指集合…