ACM集训队阶段总结课件_第1页
ACM集训队阶段总结课件_第2页
ACM集训队阶段总结课件_第3页
ACM集训队阶段总结课件_第4页
ACM集训队阶段总结课件_第5页
已阅读5页,还剩147页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、浙江林学院ACM集训队阶段总结Write by Zhuangli(zjfc3) 第1页,共152页。图论What is that?第2页,共152页。什么是图论?图论Graph Theory是数学的一个分支。它以图为研究对象。图论中的图是由若 干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系,用点代表事物,用连接两点的线表示相应两个事物间具有这种关系 。 图论本身是应用数学的一部份,因此,历史上图论曾经被好多位数学家各自独立地建立过。关于图论的文字记载最早出现在欧拉1736年的论着中,他所考虑的原始问题有很强的实际背景。 第3页,共152页。并查集及其拓展并

2、查集是一种信息内聚很强的数据结构,它在判定图的连通性以及等价类划分的时空效率上有着不可替代的优势。但并查集的特殊应用也应该有所了解.以下两类是并查集在实际问题中的特殊拓展,希望大家能够进行快速掌握.1.集合计数问题2.二分图识别第4页,共152页。集合计数问题HDU 1856 More is better题意:若A与B认识,B与C认识,则A与C认识,现给你一组人员的关系表,求在这样的不同群组内,拥有最多人数群组的人数。第5页,共152页。集合计数问题有什么想法?并查后统计并查数组?不可行 数据范围10000000 如果逐个统计必定TLE 不能如此暴力.思路如何想3分钟第6页,共152页。集合计

3、数问题联想到并查集的构造原理构造rank数组,在并操作中入手!好,问题解决! 第7页,共152页。二分图识别HDU 1829 A Bug Of Life题意:假定两只飞虫(Bug)关系表,如A B表示A仰慕B,问是否存在同性的飞虫互相仰慕(也就是同性恋问题).第8页,共152页。二分图识别难点:A与B的集合归属不定如何解决?思考!第9页,共152页。二分图识别非此即彼思想的运用构造数组opp,初始化为本身编号,若A与B有关,首先进行find(A),find(B)的操作,若根相同,则说明A与B属于同一集合,即同性恋,否则执行下面的操作,如果A的opp等于本身,说明A的opp未初始化,使之等于B,

4、否则将A的opp与B进行Unition操作,类似的如果B的opp等于本身,说明B的opp未初始化,使之等于A,否则将B的opp与A进行Unition操作第10页,共152页。二分图识别想想为什么?二分图的性质决定更深入的二分识别(如统计最小单元集,如何进行 _ 课后思考!)第11页,共152页。最短路径问题在一个网络图中求解一点到另一点间最短距离及其路径的算法称之为最短路径问题。1、单源正权最短路径2、单源带负权最短路径3、多源最短路径第12页,共152页。单源正权最短路径求解单源最短路径的Dijkstra算法,状态转移与贪心准则的完美结合。思想:动态规划 策略:贪心( O(Ve) )步骤:1

5、.构造辅助数组Dis,Vist,Disi表示从源点出发到达i点的最短距离,Visti表示i点是否已被访问,算法开始执行时令所有Disi=w(start,i)不可达为MAX,Viststart=true.2.每次得到Dis数组中最小且未被访问过的点i,标记Visti=true,遍历所有与i相关的边,若得到Disi+w(i,j)Disj,则更新Disj=Disi+w(i ,j).3.如此循环直到所有点均被标记.第13页,共152页。单源正权最短路径Dijkstra的致命弱点:不能处理带负权的边思考:Why?问题出自贪心策略!若存在负权,则算法将不断更新负权边相关顶点的Dis值,从而导致答案错误!第

6、14页,共152页。单源带负权最短路径如何处理Dijkstra的遗留问题?摈弃贪心策略 执行松弛技术-Bellman-ford算法第15页,共152页。单源带负权最短路径什么是松弛技术?日常生活中的例子(1+1猜想)松弛技术的本质是首先给予一个物体很高的估价,在每次的迭代中对估价进行修正,在有限次的迭代后使估价与实际值吻合的技术。第16页,共152页。单源带负权最短路径思想:若存在N个点的网络,则对于起点到终点最多经过N-1条边策略:有限迭代下的松弛技术第17页,共152页。单源带负权最短路径步骤:1、开辟辅助数组Dis,记录源点到点i的最小距离,初始时设所有Dis值为MAX,Disstart

7、=0.2、进行n-1次迭代,对于所有边,若满足DisiMAX&Disi+w(i,j)Disj,更新Disj= Disi+w(i,j).3、执行完成后,再执行1次迭代,若出现Disi+w(i,j)Disj的情况,则表明出现了负环,此时不存在最短路径,否则Disend即所求单源最短路径.第18页,共152页。单源带负权最短路径算法分析:1、迭代v-1次,每次遍历所有边,复杂度O(VE),E为全部边,Dijkstra的复杂度O(Ve),e为部分边.效率差别很大!2、如何优化?思考!第19页,共152页。单源带负权最短路径优化1:使用bool值Y 标记此次迭代是否进行松弛,若没进行松弛表明已经得到最短

8、路径,因此跳出循环。(常系数优化)-YEN氏优化优化2:使用标记数组以及队列辅助,初始化时推入start点,标记start在队内,每次执行时,将队首推出,标记其不在队内,遍历其邻边,进行松弛操作,将所有不在队内且进行过松弛操作的边相关的点入队直到队列为空(即不再进行松弛操作)-SPFA!第20页,共152页。单源带负权最短路径由优化2得到的正是传说中的SPFA,拥有神一般的效率O(KE),K一般取值3-5。算法如其名Shortest Path Fast Algorithm!瓶颈:如何判负环?思考!当一个点入队次数超过边的次数!需要辅助数组统计各点入队次数,此时的空间与时间效率都极低!因此此算法

9、在稠密带负环图中的表现不如bellman-ford的YEN氏优化!请大家慎重选择使用。第21页,共152页。多源最短路径当题目要求大量的查询工作时,需要一种算法能在多项式时间内得到所有顶点间的最短距离并保存结果备查。Floyed算法应运而生!第22页,共152页。多源最短路径思想:传递关系闭包策略:动态规划O (V*V*V)步骤:1、对于点k,若存在w(i,k)+w(k,j)=(或=)C(常数),以此为模型构成的约束系统,称之为差分约束系统。第36页,共152页。差分约束初步首先我们回顾下松弛技术,在Bellman-Ford算法中,有一个十分关键的三角不等式Disi+w(i,j)Disj使得迭

10、代结束后所有的Disj=(或=)C,我们取=情况研究,则要求xi-xj=C,即xi=wi,j始终 成立。KM算法的正确性基于以下定理: 若由二分图中所有满足Ai+Bj=wi,j的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配。这个定理是显然的。因为对于二分图的任意一个匹配,如果它包含于相等子图,那么它的边权和等于所有顶点的顶标和;如果它有的边不包含于相等子图,那么它的边权和小于所有顶点的顶标和。所以相等子图的完备匹配一定是二分图的最大权匹配。 算法的本质是对匈牙利算法的改进,但实际上却比匈牙利算法早发表几年,其核心仍然是寻找增广路径的过程。第42页,共

11、152页。KM算法步骤初始时为了使Ai+Bj=wi,j恒成立,令Ai为所有与顶点Xi关联的边的最大权,Bj=0。如果当前的相等子图没有完备匹配,就按下面的方法修改顶标以使扩大相等子图,直到相等子图具有完备匹配为止。 我们求当前相等子图的完备匹配失败了,是因为对于某个X顶点,我们找不到一条从它出发的交错路。这时我们获得了一棵交错树,它的叶子结点全部是X顶点。现在我们把交错树中X顶点的顶标全都减小某个值d,Y顶点的顶标全都增加同一个值d,那么我们会发现: 两端都在交错树中的边(i,j),Ai+Bj的值没有变化。也就是说,它原来属于相等子图,现在仍属于相等子图。 两端都不在交错树中的边(i,j),A

12、i和Bj都没有变化。也就是说,它原来属于(或不属于)相等子图,现在仍属于(或不属于)相等子图。 X端不在交错树中,Y端在交错树中的边(i,j),它的Ai+Bj的值有所增大。它原来不属于相等子图,现在仍不属于相等子图。 X端在交错树中,Y端不在交错树中的边(i,j),它的Ai+Bj的值有所减小。也就说,它原来不属于相等子图,现在可能进入了相等子图,因而使相等子图得到了扩大。 现在的问题就是求d值了。为了使Ai+Bj=wi,j始终成立,且至少有一条边进入相等子图,d应该等于minAi+Bj-wi,j|Xi在交错树中,Yi不在交错树中。 理解原理就行,在一般情况下KM算法的代码不会调整,因此只要会使

13、用模版,一切不在话下,当然图论本身就是充满了建模的思想,只有好的模型才能有真正的效率!第43页,共152页。KM算法效率 O(V*V*V)KM算法的本质,对于N*N的矩阵每行每列只能取一个数,使其和为最大!第44页,共152页。强连通分支什么是强连通分支?强连通分支就是任意两点均可达的有向子图。理论:白色路径定理求解:Tarjan算法第45页,共152页。强连通分支什么是时间戳?DFS进行时,访问到节点所花的时间算法理论依据:DFS时,如果所达的下一个点i已经被访问,则从该点j出发,寻找父节点到i,其间所经过的所有点必为以i为代表的强连通分支上的点(并查实现)如何判断是否是该次被访问?时间戳!

14、第46页,共152页。强连通分支步骤对于每个顶点,设立Num、Low、Used、Alive四个属性,一个Stack保存当前正在被遍历的顶点;每访问一个顶点,将它的Num和Low设立为当前时间戳,Used、Alive设为True,并将顶点入栈;对于它的每条边,若边的终点未Used,则访问,而后用终点的Low值更新它的Low值,对于每个Used且Alive的终点,用它的Num值更新当前值;访问完毕当前顶点后,若Low与Num相等,说明找到了一个强连通分量,它包括栈中所有在当前顶点上方的顶点,将它们出栈并记下Belong值,出栈的顶点的Alive要置为false。扫描各点Belong值,其代表的点的

15、个数便为强连通分支数!第47页,共152页。强连通分支应用1、求解单纯问题 HDU 12692、缩图技术 (适用于多点多边的关系闭包求解)第48页,共152页。待研究的问题次小生成树最优比例生成树最小树型图弦图稳定婚姻问题第49页,共152页。数论Its easy to learn!第50页,共152页。数论什么是数论?数论是研究整数性质的一门很古老的数学分支, 其初等部分是以整数的整除性为中心的,包括整除性、不定方程、同余式、连分数、素数(即整数)分布 以及数论函数等内容,统称初等数论(elementary number theory)。 初等数论的大部份内容早在古希腊欧几里德的 几何原本中

16、就已出现。欧几里得证明了素数有无穷多个,他还给出求两个自然数的最大公约数的方法, 即所谓欧几里得算法。我国古代在数论方面亦有杰出之贡献,现在一般数论书中的中国剩余定理正是我国古代孙子算经中的下卷第26题,我国称之为 孙子定理。 近代初等数论的发展得益于费马、欧拉、拉格朗日、勒让德和高斯等人的工作。1801年,高斯的算术探究是数论的划时代杰作。高斯还提出:数学是科学的皇后,数论是数学中的皇冠。可见高斯对数论的高度评价。 由于自20世纪以来引进了抽象数学和高等分析的 巧妙工具,数论得到进一步的发展,从而开阔了新的研究领域,出现了代数数论、解析数论、几何数论等 新分支。而且近年来初等数论在计算器科学

17、、组合数学、密码学、代数编码、计算方法等领域内更得到了广泛的应用,无疑同时间促进着数论的发展。 第51页,共152页。同余定理对于正整数a,b,c(a%c+b%c)%c=(a+b)%c(a*b)%c=(a%c*b%c)%c注意对于除法与减法%运算为非封闭运算 需要进行数论变换才能继续进行下去第52页,共152页。同余定理大数求余设大数R=a1*100+a2*101+.+an*10n-1则R%C=(a1*100%C+a2*101%C+.+an*10n-1%C)%C可以在O(logn)时间内解决大数求余问题步骤:以字符读入大数后,设置计数器sum=0 sum=(10*sum+keyi-0)%C;迭

18、代后令sum=sum%C;第53页,共152页。GCDGCD(最大公约数)的一般求解欧几里德辗转相除法(必须掌握)If(a%b=0) return b;Else return gcd(b,a%b);本过程具有收敛性质第54页,共152页。扩展欧几里德在一些具体的题目中,我们还需要的到一组满足ax+by=gcd(a,b)的最小解,用以判断模方程是否有解,此时就要使用扩展欧几里德.相比一般欧几里德方法,扩展欧几里德有一个对于X,Y求解的递推过程。使用递归实现,递归条件为b=0时,X=1,Y=0;否则t=X; X=Y; Y=t-(a/b)*X;(递推求得)可以证明最后出来的X,Y必然是最小解.应用:

19、模线性方程的求解第55页,共152页。循环群生成元对于mod n域中的任意数a,若有gcd(m,n)=1,则m为该域的生成元,使得a+km可以为域中任意数.证明十分简单,若gcd(m,n)=1,则lcm(m,n)=m*n,则对于a的mod n运算,需要n次的计算才能回到a,期间必遍历该域中所有数!第56页,共152页。因子分解对于筛选大量数的因子分解工作,可以与筛选质数同时进行。令leni记录数i的因子个数,则对于每个素数p的倍数及本身,插入因子p,并使len值增长,筛选完所有素数后就完成了因子分解第57页,共152页。素数判定对于一千万内素数的判定:筛选法最优对于一千万外素数的判定:米勒测试

20、第58页,共152页。筛选法给定辅助bool数组prime,首先全置true,使prime0=prime1=false;遍历,当遇到primei=true,将之小于n的所有倍数置false;最后一次遍历,所有值为true的数即为素数!时空效率 均摊相关伪线性复杂度第59页,共152页。米勒测试理论基础费马定理实践工具二分求幂第60页,共152页。米勒测试费马定理:若p为素数-a(p-1)%p=1注意此定理只为充分 不为必要米勒测试以概率的形式避免了误判的发生 从严格意义上来说米勒测试的意义并不科学 但是实际证明在可数范围内的伪素数十分之少 而且同时满足a=2,a=3,a=7的底的伪素数更是少得

21、可怜,因此该测试从概率上满足了快速判定素数的需求。第61页,共152页。米勒测试二分快速求幂模原理对于res=ab%c的求解若b%2=0则res=(a(b/2)%c*(a(b/2)%c)%c否则res=(a*(a(b/2)%c*(a(b/2)%c)%c第62页,共152页。欧拉函数设E(n)为n以内(不包括n)与n互质数的个数,则E(n)称为关于n的欧拉函数。欧拉函数的求法,对于n=p1*p2*p3pnE(n)=n*(1-1/p1)*(1-1/p2)*(1-1/pn)可以以容斥原理证明其正确性!欧拉定理: a(E(n)%n=1第63页,共152页。模线性方程求解axb(mod n)有解,当且仅

22、当b%gcd(a,n)=0使用扩展欧几里德求得d=gcd(a,n),则aX+nY=d,x=(X*(b/d)%nWhy?b/d=m a(X*m)+nY*m=b=x=(X*m)%n第64页,共152页。中国剩余定理设 n=n1*n2.nk, 其中因子两两互质.有: a-(a1,a2,.,ak), 其中ai = a mod ni, 则 a和(a1,a2,.,ak),关系是一一对应的.就是说可以由 a求出(a1,a2,.,ak), 也可以由(a1,a2,.,ak)求出a求解:中国古代演算法模线性方程代入第65页,共152页。中国剩余定理应用大整数表示快速运算第66页,共152页。连分数逼近在数学中,连

23、分数或繁分数即如上表达式.这里的 a0 是某个整数而所有其他的数 an 都是正整数。可依样定义出更长的表达式。如果部分分子(partial numerator)和部分分母(partial denominator)允许假定任意的值,在某些上下文中可以包含函数,则最终的表达式是广义连分数。在需要把上述标准形式与广义连分数相区别的时候,可称它为简单或正规连分数,或称为是规范形式的一个数的连分数表示是有限的,当且仅当这个数是有理数。 “简单”有理数的连分数表示是简短的。 任何有理数的连分数表示是唯一的,如果它没有尾随的 1。(但是 a0; a1, . an, 1 = a0; a1, . an + 1。

24、) 无理数的连分数表示是唯一的。 连分数的项将会重复,当且仅当它是一个二次无理数(即整数系数的二次方程的实数解)的连分数表示。 数 x 的截断连分数表示很早产生 x 的在特定意义上“最佳可能”的有理数逼近。 第67页,共152页。连分数逼近意义1、精度保留2、避免浮点运算3、无理数的表示唯一4、研究连分数的动机源于想要有实数在“数学上纯粹”的表示。求解欧几里德变体!第68页,共152页。连分数逼近 第69页,共152页。数据结构Soul !第70页,共152页。数据结构什么是数据结构?数据结构是计算机存储、组织数据的方式。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率的算法。数据

25、结构往往同高效的检索算法和索引技术有关。 数据结构在计算机科学界至今没有标准的定义。个人根据各自的理解而有不同的表述方法:Sartaj Sahni 在他的数据结构、算法与应用一书中称:“数据结构是数据对象,以及存在于该对象的实例和组成实例的数据元素之间的各种联系。这些联系可以通过定义相关的函数来给出。”他将数据对象(data object)定义为“一个数据对象是实例或值的集合”。Clifford A.Shaffer 在数据结构与算法分析一书中的定义是:“数据结构是 ADT(抽象数据类型 Abstract Data Type) 的物理实现。”Lobert L.Kruse 在数据结构与程序设计一书

26、中,将一个数据结构的设计过程分成抽象层、数据结构层和实现层。其中,抽象层是指抽象数据类型层,它讨论数据的逻辑结构及其运算,数据结构层和实现层讨论一个数据结构的表示和在计算机内的存储细节以及运算的实现。第71页,共152页。数据结构为什么要使用数据结构?1、便于理清结构,易于表示出一个实体的内部属性与外部联系。2、更好利用实体特性,从而为算法高效铺路。3、强有力的数据结构,能够取代算法的优势。第72页,共152页。数据结构数据结构的基本类型:1、顺序表2、链表3、广义表4、树5、图6、串第73页,共152页。顺序表顺序表是在内存上开辟的连续片段,每个元素单元拥有固定大小,以此组织形成的数据结构。

27、优点:1、随机存取2、索引唯一3、结构简单第74页,共152页。顺序表一般应用:1、寄存数组(包括栈和队列)2、哈希数组3、树状数组第75页,共152页。寄存数组这是我们最常见的顺序表表现方式,一般的大数据量程序,如果不能有边读边处理的方法,就需要首先保留所有的输入,从而能够在而后的过程中进行处理。主要应用:1、各类算法的线性预处理2、保留线性逻辑关系3、记忆化辅助第76页,共152页。寄存数组优点:1、静态2、随机3、高效缺点:1、插入与删除操作效率极度低下2、内存分配不灵活技巧:1、满足递推与DP内存需求滚动数组2、满足图的快速判重化行为数 状态压缩第77页,共152页。哈希数组什么是哈希

28、?从广义上说哈希是一种键值对应的操作,是从数域到值域的一一映射,也就是我们通常称其为哈希函数的由来。为什么哈希表可以用数组实现?数组满足哈希的3个必要条件:1、键index2、值value3、键值映射(index-value)O(1)第78页,共152页。哈希数组散列函数的选用一般情况下我们使用哈希数组,采用的是开放散列策略,也就是说内存与键是一一对应,即hashkey=value,在对于key值要求不大的情况下是很好的选择。然而当要求的key很大时该怎么办,此时就应该选用一个好的映射函数使hashf(key)=value,且f(key)的值必定均匀分布在映射区间内。当然要找到这样的函数是十分

29、困难的,我们无法了解到数据的具体信息,因此一般的f(key)为key%p,p为一个质数,结合数论知识,我们可以知道当gcd(key,p)=1时,key是一个循环群生成元,使用这个性质,我们可以少了许多因大多数冲突而引发避免策略造成的效率问题。第79页,共152页。哈希数组HDU 2192题意 :递增的序列组成一个集合 请问至少有几个?思路?第80页,共152页。哈希数组出现次数最多的数,决定了能分成的最少群落!实现方式?哈希!散列函数如何刻画?思考!根据问题的输入规模,最大104个数,因此选取大于104的质数作为散列函数的参数,令f(key)=key%p还有什么问题?思考出现冲突!第81页,共

30、152页。哈希数组解决方案:1、线性扫描法2、二次线性扫描3、桶链问题完美解决,注意各个结点在不同解决方案下添加的相关变量。第82页,共152页。树状数组首先我们得知道一个问题,那就是线段树的作用并不只是用来存储线段的,也可以存储点的值等等.对于静态的线段树,空间上需要的数组有:当前结点的数据值,左儿子编号,右儿子编号.至少这么三个数组.而在时间上虽然是NlogN的复杂度,但是系数很大.实现起来的时候编程复杂度大,空间复杂度大,时间效率也不是很理想.第83页,共152页。有!那就是树状数组!那么是否有更好的解决方法呢?第84页,共152页。树状数组先看一个例题:数列操作: 给定一个初始值都为0

31、的序列,动态地修改一些位置上的数字,加上一个数,减去一个数,或者乘上一个数,然后动态地提出问题,问题的形式是求出一段数字的和.第85页,共152页。树状数组如果直接做的话,修改的复杂度是O(1),询问的复杂度是O(N),M次询问的复杂度是M*N.M,N的范围可以有100000以上第86页,共152页。用线段树可以这样解:若要维护的序列范围是0.5,先构造下面的一棵线段树:第87页,共152页。树状数组可以看出,这棵树的构造用二分便可以实现.复杂度是2*N.每个结点用数组a来表示该结点所表示范围内的数据之和.修改一个位置上数字的值,就是修改一个叶子结点的值,而当程序由叶子结点返回根节点的同时顺便

32、修改掉路径上的结点的a数组的值. 对于询问的回答,可以直接查找i.j范围内的值,遇到分叉时就兵分两路,最后在合起来.也可以先找出0.i-1的值和0.j的值,两个值减一减就行了.后者的实际操作次数比前者小一些.这样修改与维护的复杂度是logN.询问的复杂度也是logN,对于M次询问,复杂度是MlogN.第88页,共152页。树状数组用树状数组!然而不难发现,线段树的编程复杂度大,空间复杂度大,时间效率也不高.怎么办第89页,共152页。树状数组下图中的C数组就是树状数组,a数组是原数组先自己研究一下这个东西第90页,共152页。树状数组可以发现这些规律C1=a1C2=a1+a2C3=a3C4=a

33、1+a2+a3+a4C5=a5C8=a1+a2+a3+a4+a5+a6+a7+a8C2n=a1+a2+.+a2n第91页,共152页。树状数组对于序列a,我们设一个数组C定义Ci = ai 2k + 1 + + ai,k为i在二进制下末尾0的个数。K的计算可以这样:2k=x and (x xor (x-1) 以6为例 (6)10=(0110)2xor 6-1=(5)10=(0101)2 (0011)2and (6)10=(0110)2 (0010)2第92页,共152页。树状数组function Lowbit(x: Integer): Integer;begin Lowbit := x and

34、 (x xor (x 1);end;若要修改ai的值,则C数组的修改是:Procedure change(k,delta:integer);Begin while k0 do begin t:=t+ck; k:=k-lowbit(k); end; getsum:=t;End;第94页,共152页。树状数组对于刚才的一题,每次修改与询问都是对C数组做处理.空间复杂度有3N降为N,时间效率也有所提高.编程复杂度更是降了不少.在很多的情况下,线段树都可以用树状数组实现.凡是能用树状数组的一定能用线段树.当题目不满足减法原则的时候,就只能用线段树,不能用树状数组.例如数列操作如果让我们求出一段数字中最

35、大或者最小的数字,就不能用树状数组了.第95页,共152页。链表链表是内存中不连续块链接而成的数据结构,本着使用多少分配多少的原则,极大地节约和利用了内存,是一种十分基础的数据结构。优势:1、动态分配2、快速删除与插入3、节省空间第96页,共152页。链表缺点:1、查找效率低下2、动态分配结点调用操作系统实现,导致空间分配效率消耗一种对空间的优化:内存静态化!一般应用1、桶2、跳跃表第97页,共152页。桶一般用做哈希的冲突避免策略,使用桶结构存储在同一冲突域下的数据,作为键值的扩展。基数数排序的辅助结构。第98页,共152页。跳跃表可以看做是链表结构最优秀的应用,使用跳跃表有着令人震撼的效率

36、,对查询、删除和添加的操作均为O(logn)的复杂度。利用了链表自身的特点,以较小的空间代价提升了自身的性能。使用了概率算法,使效率堪与AVL、RB-Tree等BST相媲美。相比而言,极低的编程复杂度!有什么理由可以不去掌握呢?第99页,共152页。跳跃表跳跃表由多条链构成(S0,S1,S2 ,Sh),且满足如下三个条件:每条链必须包含两个特殊元素:+ 和 -S0包含所有的元素,并且所有链中的元素按照升序排列。每条链中的元素集合必须包含于序数较小的链的元素集合,即:53 53 53 45 45 37 30 30 30 29 15 11 11 11 11 - - - - + + + + S0 S

37、1 S2 S3 跳跃表的实例第100页,共152页。跳跃表之查找目的:在跳跃表中查找一个元素 x在跳跃表中查找一个元素x,按照如下几个步骤进行:从最上层的链(Sh)的开头开始假设当前位置为p,它向右指向的节点为q(p与q不一定相邻),且q的值为y。将y与x作比较x=y输出查询成功,输出相关信息xy从p向右移动到q的位置xy从p向下移动一格如果当前位置在最底层的链中(S0),且还要往下移动的话,则输出查询失败53 53 53 45 45 37 30 30 30 29 15 11 11 11 11 - - - - + + + + 查询元素53的全过程S0 S1 S2 S3 查找成功!第101页,共

38、152页。跳跃表之插入目的:在跳跃表中插入一个元素 x插入操作由两部分组成:查找插入的位置和插入对应元素。为了确定插入的“列高”,我们引入一个随机决策模块:产生一个0到1的随机数rr random()如果r小于一个概率因子P,则执行方案A,if r dist(right(A),交换left(A) 和right(A)最后,由于right(A) 的距离可能发生改变,我们必须更新A的距离:dist(A) dist(right(A) + 1不难验证,经这样合并后的树C符合性质1和性质2,因此是一棵左偏树。至此左偏树的合并就完成了。第123页,共152页。左偏树合并操作都是一直沿着两棵左偏树的最右路径进

39、行的。一棵N个节点的左偏树,最右路径上最多有 log(N+1) 个节点。因此,合并操作的时间复杂度为:O(log N1 + log N2) = O(log N)合并操作的代码如下:Function Merge(A, B)If A = NULL Then return BIf B = NULL Then return AIf key(B) dist(left(A) Thenswap(left(A), right(A)If right(A) = NULL Then dist(A) 0Else dist(A) dist(right(A) + 1return AEnd Function第124页,共1

40、52页。左偏树左偏树的特点:时空效率高编程复杂度低左偏树的应用:可并堆优先队列第125页,共152页。左偏树HDU 1512题意:刚开始所有的猴子自成一群且互相都不认识,他们互相认识当且仅当他们各自群中最强的猴子互相打了一场,体力各减为一半。问最后这群猴子中体力最强猴子的体力是多少思路如何?第126页,共152页。左偏树并查?可行,但只能作为辅助手段。优先队列+并查?O(nlogn)的合并效率实在不敢恭维很好。左偏树开始发挥了效力了!第127页,共152页。左偏树步骤:使用并查集(这里其实准确来说应该是一种记录父结点编号的数组)记录各结点在各自堆中的父结点查询两只猴子所在堆的根结点,如果两只猴

41、子根结点相同,则不必打架,否则,取各自堆中最大元素(也就是根结点)打一场打架,此时先让各自堆中根的左右儿子指向本身,再对左右儿子进行合并生成新树(即pop操作)并适当修改父结点数组,令根结点值减半后与新树再次合并,并适时修改父结点数组(即push操作),再将两个堆中的根进行合并(即unition操作)。是不是很简单的实现?第128页,共152页。斜堆如何对左偏树进行优化?思考!我们注意到在左偏树中必须要有距离的概念,但我们可以发现一个性质,如果每次合并都向右进行,每次完成后将右边的结点甩到左边,不正好符合了左偏的性质么?很好去掉距离,提高效率,优化的王道!不足(单次合并可能退化到O(n),但实

42、际效果上,两者都差不多)第129页,共152页。AC自动机AC自动机是由Aho和Corasick提出的数据结构,是对Trie树的一种改造,是对find操作的修正,也是多模式串匹配的基本实现!HDU 2222题意给你N个关键字,以及一句描述,问有多少个关键字在这句描述中出现?思路?第130页,共152页。AC自动机采用普通方法?O(Nnm)m=50,n=1000000,N=10000黄花菜都凉了KMP?O(N(m+n)?就这点优化?塞牙缝都不够那怎么办!AC自动机!O(Nm+n)强大!第131页,共152页。AC自动机步骤将所有关键字塞入Trie好了,现在我们已经有一棵Trie了,但这还不够,我

43、们还要在Trie上引入一个很强大的东西:失败指针或者说shift数组或者说Next函数 .你爱怎么叫怎么叫吧,反正就是KMP的精华所在,这也是我为什么叫你看KMP的原因。KMP中我们用两个指针i和j分别表示,Ai-j+ 1.i与B1.j完全相等。也就是说,i是不断增加的,随着i的增加j相应地变化,且j满足以Ai结尾的长度为j的字符串正好匹配B串的前 j个字符,当Ai+1Bj+1,KMP的策略是调整j的位置(减小j值)使得Ai-j+1.i与B1.j保持匹配且新的Bj+1恰好与Ai+1匹配(从而使得i和j能继续增加)。Trie树上的失败指针与此类似。第132页,共152页。AC自动机假设有一个节点

44、k,他的失败指针指向j。那么k,j满足这个性质:设root到j的距离为n,则从k之上的第n个节点到k所组成的长度为n的单词,与从root到j所组成的单词相同。那么我们要怎样构建这个东西呢?其实我们可以用一个简单的BFS搞定这一切。对于每个节点,我们可以这样处理:设这个节点上的字母为C,沿着他父亲的失败指针走,直到走到一个节点,他的儿子中也有字母为C的节点。然后把当前节点的失败指针指向那个字目也为C的儿子。如果一直走到了root都没找到,那就把失败指针指向root最开始,我们把root加入队列(root的失败指针显然指向自己),这以后我们每处理一个点,就把它的所有儿子加入队列,直到搞完。好了,现

45、在我们有了一棵带失败指针的Trie了 !可以开始进行AC自动机了!第133页,共152页。AC自动机一开始,Trie中有一个指针t1指向root,待匹配串(也就是“文章”)中有一个指针t2指向串头。接下来的操作和KMP很相似:如果t2指向的字母,是Trie树中,t1指向的节点的儿子,那么t2+1,t1改为那个儿子的编号,否则t1顺这当前节点的失败指针向上找,直到t2是t1的一个儿子,或者t1指向根。如果t1路过了一个绿色的点,那么以这个点结尾的单词就算出现过了。或者如果t1所在的点可以顺着失败指针走到一个绿色点,那么以那个绿点结尾的单词就算出现过了。本题要注意的是必须在描述串后面添加特殊符号,

46、否则将忽略对完全匹配关键字的统计。注意:BFS寻找失败指针的过程,是一个自我匹配的过程。第134页,共152页。AC自动机特点:多模式匹配的良方,一次自我适配后,对任意文章的匹配均是线性复杂度。编程复杂度较低。使用方便,居家旅行之必备!第135页,共152页。图图的结构是树结构的拓展,但在实现基本以数组的形式进行,在本质上来说所有的数据结构都是互相渗透交融的,所谓大道行简,只有掌握了本质,才能以不变应万变!基本表示:邻接阵邻接表由于上部分内容已经有所涉猎,这里就不再提过了第136页,共152页。串什么是串?串是由字符所组成的有限序列,我们只关心串的字符属性,而不关心其数值属性。串有着十分明显的

47、逻辑结构,前驱后继都是固定的,不得随意更改!关于字符串的处理一般而言都是ICPC的中档题目,如果使用模拟或者暴力方法,一般来说都是无效的。应用结构:后缀数组第137页,共152页。后缀数组什么是后缀数组?对于长度为len的字符串str,从位置i开始至len的所有字符序列称为i的后缀后缀数组(SA)保存的就是这些后缀序列的排序后的开头位置.Rank数组是SA的反函数,也就是说Ranki保存的是从位置i开始的后缀在所有后缀中的名次.第138页,共152页。后缀数组如何利用这种结构性质?我们还需要计算一个辅助的工具最长公共前缀(Longest Common Prefix)!对两个字符串u,v 定义函

48、数lcp(u,v)=maxi|u=iv,也就是从头开始顺次比较u 和v 的对应字符,对应字符持续相等的最大位置,称为这两个字符串的最长公共前缀。对正整数i,j 定义LCP(i,j)=lcp(Suffix(SAi),Suffix(SAj),其中i,j 均为1 至n 的整数。LCP(i,j)也就是后缀数组中第i 个和第j 个后缀的最长公共前缀的长度。关于LCP 有两个显而易见的性质:性质2.1 LCP(i,j)=LCP(j,i)性质2.2 LCP(i,i)=len(Suffix(SAi)=n-SAi+1这两个性质的用处在于,我们计算LCP(i,j)时只需要考虑ij时可交换i,j,i=j时可以直接输

49、出结果n-SAi+1。第139页,共152页。后缀数组直接根据定义,用顺次比较对应字符的方法来计算LCP(i,j)显然是很低效的,时间复杂度为O(n),所以我们必须进行适当的预处理以降低每次计算LCP的复杂度。经过仔细分析,我们发现LCP 函数有一个非常好的性质:设ij,则LCP(i,j)=minLCP(k-1,k)|i+1kj (LCP Theorem)根据LCP Theorem得出必然的一个推论:LCP Corollary 对ijk,LCP(j,k)LCP(i,k)。第140页,共152页。后缀数组定义一维数组height,令heighti=LCP(i-1,i),11 且Ranki1,一定有hihi-1-1。根据性质3,可以令i从1 循环到n按照如下方法依次算出hi:若Ranki=1,则h

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论