首页 Trie图的构建、活用与改进

Trie图的构建、活用与改进

举报
开通vip

Trie图的构建、活用与改进2006年全国信息学冬令营讲座Trie图的构建、活用与改进Maigo2006.1.14我们知道trie树(也叫字母树)这种数据结构。它是词典的一种存储方式。词典中的每一个单词在trie树中表现为一条从根结点出发的路径,路径中边上的字母连起来就形成对应的单词。图1就是一棵trie树,其中含有a,abc,bac,bbc,ca五个单词。利用trie树可以对词典中的单词进行一些适合用树这种数据结构进行的操作,如求两个单词的公共前缀长度(在树中表现为求两个单词对应结点的最近公共祖先)。其实,如果把trie树加以改造,多连一些...

Trie图的构建、活用与改进
2006年全国信息学冬令营讲座Trie图的构建、活用与改进Maigo2006.1.14我们知道trie树(也叫字母树)这种数据结构。它是词典的一种存储方式。词典中的每一个单词在trie树中 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 现为一条从根结点出发的路径,路径中边上的字母连起来就形成对应的单词。图1就是一棵trie树,其中含有a,abc,bac,bbc,ca五个单词。利用trie树可以对词典中的单词进行一些适合用树这种数据结构进行的操作,如求两个单词的公共前缀长度(在树中表现为求两个单词对应结点的最近公共祖先)。其实,如果把trie树加以改造,多连一些边,形成的trie图在解决多模式串匹配问题上会发挥奇效。左:图1,一棵含有五个单词的trie树。红色表示单词终止的位置。右:图2,由图1的trie树改造成的trie图。红色表示危险结点,白色表示真安全结点,蓝色表示新加的边。为简单起见,危险结点以下的结点及与之关联的边没有画出。一、Trie图的构建我们通过一个例题来探究trie图的构建 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 。【例1】不良单词探测器【题目描述】给出一个词典,其中的单词为不良单词。单词均为小写字母。再给出一段文本,文本的每一行也由小写字母构成。判断文本中是否含有任何不良单词。例如,若rob是不良单词,那么文本problem含有不良单词。【输入】第一行为一个整数n,表示不良单词的个数。接下来n行是词典。下面一行为一个整数m,表示文本的行数。接下来m行是文本。【输出】如果文本包含不良单词,输出一行“Yes”,否则输出一行“No”。【样例输入】1rob1internetproblemsolvingcontest【样例输出】Yes【备注】因本题只是用来讨论trie图的构建方法,故未给出数据范围。【分析】判断文本是否包含不良单词可以一行一行地判断。而判断长为L的一行文本s是否含有不良单词可以这样进行:让i从1变化到L,依次判断s的前i个字符构成的字符串是否以不良单词结尾。2006年全国信息学冬令营讲座然而,我们希望在判断s的前k个字符时,能够利用前k-1个字符的结果,即这两个状态间可以方便地进行转移。注意到trie树中的边正如一个个“方向标”,因此我们有了一个美好的设想:从根结点出发,沿着标有s[1]的边走一步,再沿标有s[2]的边走一步,一直这样走下去!现在有了一个问题:如果从当前走到的结点出发,没有需要走的边,该怎么办?只要“创造”一条这样的边即可。那么这条边应该指向哪个结点呢?如果同样“创造”一个结点,那是毫无意义的。解决这个问题,要从我们“沿边走”的动机谈起。我们之所以“沿边走”,是因为我们把结点看成了状态,把边看成了状态间转移的途径。要确定新加的边应连到哪个结点,就需要找我们想走到但去不存在的那个结点与已有的哪个结点是等价的。那么“等价”的标准是什么呢?我们先来解决另一个问题:定义trie树中从根结点到某个结点的路径上的边上的字符连起来形成的字符串为这个结点的路径字符串。如果一个结点的路径字符串以不良单词结尾,那么称这个结点为危险结点,否则称之为安全结点。那么如何判断某个结点是否危险呢?显然根结点是安全结点。对于一个非根结点,它是危险结点的充要条件是:它的路径字符串本身就是一个不良单词,或者它的路径字符串的后缀(一个字符串去掉第一个字符后剩下的部分叫做它的后缀)对应的结点(一个字符串对应的结点是指在trie图中从根出发,依次沿该字符串的每个字符走一步所达到的结点)是危险结点。如果称一个结点的路径字符串的后缀对应的结点为它的后缀结点,那么如何求任一结点的后缀结点呢?根结点的后缀结点是它本身。处于trie树第二层的结点的后缀结点也是根结点。对于再往下的某个结点,设它的路径字符串的最后一个字符为c,那么这个结点的后缀为从它在trie树中父结点的后缀结点出发,沿标有c的边走一步后到达的结点。(下文中称从x结点出发,沿标有字符c的边走一步到达的结点为x的c孩子)那么,如果它的父结点的后缀结点w没有c孩子怎么办呢?到此,我们看到两个问题已经合而为一了。我们假设w有这样一个c孩子(记作x),并且从x出发又繁衍出无数的子子孙孙。我们来判断以x为根的子树中的结点的危险性。显然x本身的路径字符串不是不良单词,且它的子孙的路径字符串也不是不良单词。因此以x为根的子树中任一结点y的危险性与y的后缀结点的危险性相同(回忆一下一个非根结点是危险结点的充要条件)。这也就是说,以x为根的子树与以x的后缀结点为根的子树是一模一样的。因此,我们把需要新建的从w指向x的边直接指向x的后缀结点,即w结点的后缀结点的c孩子即可。简言之,由于x本身的路径字符串既不是不良单词,又不是某个不良单词开头的一部分,所以它的首字母便没有用了!在这种情况下,x结点就等价于它的后缀结点。由此我们可以把trie树改造成一个有向图:按层次遍历trie树,求出每个结点的危险性和后缀结点,并补齐由它出发的边。危险性与后缀结点的求法在【分析】部分第6、7自然段已有说明;若当前结点为根结点,则补充的边应指向本身,否则若x没有c孩子,则新建一条这样的边,指向x的后缀结点的c孩子。处理某个结点的过程中需要用到深度比它小的结点的后缀结点及各个孩子。由于我们按层次遍历trie树,这些信息都已求得。这样由trie树改造成的有向图就叫做trie图。图2就是由图1的trie树改造成的trie图。我们美好的设想终于变成了现实。由根结点出发,按照文本中的字符一步步走下去。若走到一个危险结点,则发现了一个不良单词;若一直没走到危险结点,则文本不含不良单词。本题的算法还可稍加优化。把安全结点分为两类:如果在trie树中由根结点到某个安全结点的路径上没有危险结点,那么称这个安全结点为真安全结点,否则称之为假安全结点。由于新建的边的终点的深度不会大于起点的深度,因此要到达一个假安全结点,必须经过一2006年全国信息学冬令营讲座个危险结点。而在本题中,一旦到达一个危险结点,程序就会停止,因此假安全结点是没有用的,也就是说,在本题trie图的构建过程中,若发现一个危险结点,那么它及它的子孙的属性都不必计算了。如果用L1、L2分别表示不良单词和文本的总长度,用a表示字符集中字符的个数,那么trie图的时间复杂度为O(L1a+L2),空间复杂度为O(L1a)。二、Trie图的活用在上面的例题中,我们在trie图中 记录 混凝土 养护记录下载土方回填监理旁站记录免费下载集备记录下载集备记录下载集备记录下载 了每个结点的危险性、后缀结点,并通过按层次遍历得到了图中结点的一个BFS序。其实,trie图中可以记录的信息不止这些;得到的BFS序也并不是毫无用处。【例2】字谜(题目来源:SPOJWPUZZLES)【题目描述】给定一个L行C列的、由大写字母构成的矩阵,以及W个单词。每个单词可在矩阵中的任何位置朝着任何方向出现,且仅出现一次。编程找出每个单词的首字母在矩阵中的位置,以及单词的朝向。【输入(标准输入)】第一行为一个整数T,表示数据的组数。下面有T组数据。每组数据中:第1行为三个不超过1000的整数L、C、W。下面L行,每行C个大写字母,表示矩阵。下面W行,每行一个单词。【输出(标准输出)】对每组数据,输出W行,每行为两个整数和一个字母,之间用一个空格隔开。第i行的两个整数表示第i个单词首字母的行号和列号(从上至下依次为第0至L-1行,从左往右依次为第0至C-1列);字母表示单词的朝向,对应关系如下:字母ABCDEFGH朝向上右上右右下下左下左左上相邻两组数据的输出之间用一个空行隔开。【样例输入】1454MAIGOQKRPTAREMOWERTYAKIMAIGOARMARMY【样例输出】20B00C01D01D【分析】本题中多模式匹配的模型是显而易见的。由于要求的是每个单词首字母的位置,我2006年全国信息学冬令营讲座们在建trie图时,把每个单词都反过来,如单词MAIGO变成OGIAM。对每个方向的每一串字母进行一次多模式匹配,就可以找到所有的单词了。在本题的trie图中,仅仅记录每个结点的危险性是不够的,还要记下每个结点的危险性是由哪个单词引起的。我们定义危险结点x的危险源:若x的路径字符串本身就是不良单词,那么它的危险源就是该单词;否则x的危险源就是它后缀结点的危险源。每个结点的危险源可以在后缀结点的过程中求出。那么,是不是每走到一个危险结点,便记下危险源的位置及朝向就可以了呢?不是的。比如在样例中,当我们沿着左上方向扫描(3,4)-(0,1)这个字符串(YMRA),到达字母A时,由于该结点的危险源是YMRA,我们便记下了ARMY的位置和朝向。但同时我们就把单词ARM漏掉了。正确的做法是,当遇到一个危险结点时,记下它的危险源的位置和朝向,同时继续检查危险源对应结点的后缀结点,直到到达一个安全结点为止。【注】本题的字符集虽然只有26个字母,但trie图中结点的数目可能达到1,000,000,内存复杂度太高。这个问题留待第三部分解决。通过《字谜》一题我们学会了如何在trie图中记下更多的信息。下面简述一下对BFS序的应用。在做多模式匹配时,有时仅仅找到不良单词是不够的,还要统计出每个单词出现的次数。进行这项工作时,我们并不需要判断每个结点的危险性,而只需累加经过每个结点的次数。但这时有单词对应的结点的访问次数并不就是这个单词出现的次数,比如在图2中,单词a出现时光标完全可能在结点ba上。因此我们自底向上地把每个结点的访问次数加到它的后缀结点上。这样处理之后,有单词对应的结点的访问次数就代表这个单词出现的次数了。上面介绍了trie图的一些初步活用。但如果仅仅用trie图来做多模式匹配,那就太大材小用了。下面再通过几个例题来说明trie图的更灵活的应用。从例1可以看到,危险结点在图中往往是一些障碍,在许多用到trie图的问题中,有用的结点只有真安全结点。我们把trie图中的真安全结点以及它们之间的边构成的子图叫做安全图。【例3】病毒(题目来源:POI#7)【题目描述】已知某些特定的01串是病毒的特征代码。如果一个01串不含有任何病毒特征代码,则称它为一段安全代码。给定病毒特征库,判断是否存在无限长的安全代码。【输入(文件wir.in)】第一行为一个整数n,表示病毒特征代码的条数。下面n行,每行一段病毒特征代码。所有代码长度之和不超过30000。【输出(文件wir.out)】若存在无限长的安全代码,输出一行“TAK”,否则输出一行“NIE”。【样例输入】3011100000【样例输出】NIE【分析】“无限长”的安全代码是什么意思呢?就是说从根结点出发,在安全图中可以走无限步。“无限步”又是什么意思呢?就是说安全图中有环。因此我们建立一个trie图并对其安全图进行拓扑排序,若成功,则安全图无环,输出“NIE”,否则输出“TAK”。2006年全国信息学冬令营讲座【例4】Censored!(题目来源:Ural1158)【题目描述】已知一个由n(1<=n<=50)个字符组成的字符集及p(0<=p<=10)个不良单词(长度均不超过10),求长度为m(1<=m<=50)且不含不良单词的字符串的数目。【输入(标准输入)】第一行为三个整数n,m,p。第二行为n个字符,表示字符集。下面p行,每行一个不良单词。【输出(标准输出)】一个整数,表示长度为m且不含不良单词的字符串的数目。【样例输入】333QWEQQWEEQ【样例输出】7【分析】求长度为m且不含不良单词的字符串的数目,就是求在安全图中从根结点出发走m步有多少种走法。用count[step,x]表示从根结点出发走step步到结点x的走法数,则容易写出下面的伪代码:fillchar(count,sizeof(count),0);count[0,根]:=1;forstep:=1tomdofor安全图中每条边(i,j)doinc(count[step,j],count[step-1,i]);ans:=0;for安全图中每个结点xdoinc(ans,count[m,x]);显然,本题还需要用高精度。我们看到,trie图的安全图上还是大有文章可做的。Trie图(或其安全图)作为一个有向图,它具有一般有向图具有的性质,因此在它上面可以进行拓扑排序。同样,它的有向性也可以成为动态规划划分阶段的依据。三、Trie图的改进Trie图的空间复杂度是比较高的,当trie图中结点个数较多或字符集较大时,内存根本无法承受。下面探讨这个问题的解决方法。【例5】不良单词过滤器(题目来源:Ural1269)【题目描述】给出一个词典,其中的单词为不良单词。再给出一段文本,文本的每一行可能包含除chr(0),chr(10),chr(13)外的任何字符。若文本中有不良单词,找出文本中不良单词第一次出现的位置,若没有,输出一行“Passed”。【输入(标准输入)】第一行为一个整数n(1<=n<=10000),表示不良单词的个数。接下来n行是词典。词典的大小不超过100KB,每个不良单词的长度不超过10000。下面一行为一个整数m,表示文本的行数。接下来m行是文本。文本的大小不超过900KB。2006年全国信息学冬令营讲座【输出(标准输出)】若文本中有不良单词,输出一行两个整数,表示不良单词第一次出现的行和列,用一个空格隔开。若文本中无不良单词,输入一行“Passed”。【样例输入】2robProblem1InternetProblemSolvingContest【样例输出】110【注意】样例中“第一次出现”的不良单词是Problem而不是rob,虽然rob比Problem先结束。【时间限制】1s。【内存限制】5000KB。【分析】乍一看,这道题与例1不是一模一样的吗?其实不然。与例1相比,这道题的字符集大得多,如果直接建trie图,从每个结点出发要建253条边,而结点数最多为100000,严重超内存。试想一下,如果要做一个汉字的多模式匹配系统,岂不是要从每个结点出发建几千几万条边呢?所以,为解决此问题,trie图的改进势在必行。我们看到,在本题中,算法的瓶颈在于从每个结点出发的边数。那么我们自然会想到:一定要存储所有的边吗? 答案 八年级地理上册填图题岩土工程勘察试题省略号的作用及举例应急救援安全知识车间5s试题及答案 是否定的。Trie树中的边自然是要存储的(用左孩子右兄弟表示法),但新建的边则不必存储。如果不存储新建的边,那么如何实现状态间的转移呢?我们用一个函数child(x,c)来获得结点x的c孩子。函数内部的程序其实完全是按照加边的原则编写的:如果x本来就有c孩子,那么就返回这个孩子;如果x没有c孩子,根据加边的原则,函数应该返回x的后缀结点的c孩子,也就是令x为它的后缀结点,重新执行函数。如果x变成了根结点仍然没有c孩子,同样根据加边的原则,函数的返回值就应该是根结点本身。经过这样的处理,算法的空间复杂度由O(L1a)降到了O(L1),对于本题来说是足够低的了。但是,由于child函数的执行时间的不确定性,我们对算法的时间复杂度产生了疑问。其实,算法的时间复杂度为O(L1+L2),数量级并没有受到影响,只是增加了一点常数系数。为什么呢?显然,在调用child(x,c)的时候,只有当x没有c孩子,需要重复执行child函数时运行时间才会增加。我们分别讨论增加的这点时间对建图过程和文本检查过程所需时间的影响:—建图过程:由于我们并不存储一个结点的所有孩子指针,所以建图的过程其实就是求每个结点的后缀结点的过程。若b是trie树中a结点的一个孩子,那么b的后缀结点的深度至多比a的后缀结点大1。如果把trie树中某条路径上的结点的后缀结点的深度排成一个数列,那么相邻两项中,后一项减一项的差一定小于等于1。当后一项减前一项的差小于1时,child函数就会被重复执行。但是,child函数回溯的次数不会超过trie树的深度,所以建图过程的时间复杂度为O(L1)。—文本检查过程:把这个过程看成是一个光标在安全图中漫游的过程。因为光标如果往下走,它只能走1步,所以若把光标经过的位置的深度也排成一个数列,这个数列与上一段提到的数列具有相同的性质:增长是缓慢的。同理,文本检查过程的时间复杂度为O(L2)。综上所述,改进后的trie图的时间复杂度为O(L1+L2)。无论从时间复杂度上看还是从空间复杂度上看,改进后的算法都明显优于改进前。第二部分中的《字谜》一题到此也得到了2006年全国信息学冬令营讲座圆满解决。其实,改进后的算法已经就是用于多模式串匹配的改进KMP算法了。对于什么样的题目需要用改进的trie图,在此作一下总结:—纯粹的多模式匹配问题:当题目中的字符集大小有限且较小时,不必用改进的trie图,因为内存够用,若进行改进,增加的常数系数可能反而大于字符集的大小a。如果字符集较大甚至无限(汉字的多模式匹配系统的字符集几乎可以认为是无限的),就必须使用改进的trie图。—用到图中每一条边的题目(如第二部分中提到的拓扑排序、动态规划等):一般用未改进的trie图。在内存十分紧张的情况下,可以采用改进的trie图,用时间换空间,但这样做时间复杂度仍为O(L1a+L2),且常数系数较未改进时大。附:《病毒》一题的程序:Wir.pas《字谜》一题的程序可以在http://purety.jp/akisame/oi/SPOJ.rar下载。《Censored!》和《不良单词过滤器》的程序可以在http://purety.jp/akisame/oi/URAL.rar下载。
本文档为【Trie图的构建、活用与改进】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
个人认证用户
慢慢文档
8年外贸单证以及相关的工作经验
格式:pdf
大小:156KB
软件:PDF阅读器
页数:7
分类:管理学
上传时间:2023-02-28
浏览量:1