字符串的有关算法讲述课件.ppt
- 【下载声明】
1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
3. 本页资料《字符串的有关算法讲述课件.ppt》由用户(晟晟文业)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 字符串 有关 算法 讲述 课件
- 资源描述:
-
1、字符串的相关算法还是在前面的话 因为本人太弱所以这几天讲的ppt经常会发现错误,建议在ppt大略的基础上去找相关论文学习。可能重点还是在原理的简单解释 有的地方听不懂的话也没关系,因为每个人没有实现过代码之前实际上都是这样的,可能会对某些地方不理解不影响你对整个算法的印象。以后如果能够专门思考的话也许就会快捷许多。字符串算法有一些的原理看起来比较麻烦,但是代码量往往特别短,所以建议要去完全理解某个算法的原理,这样子以后就算把模板忘了,也许也能够通过原理写出相应的代码。一开始可以学习一下练习模板。字符串算法的模板往往很短,很容易上手。大前天提到了分治 提到了这样一个方程 f(n)=f(n/2)+
2、f(n/2)+O(1)这个咱当时是说f(n)=O(nlogn)那是咱SB Too Nave 考虑线段树的节点,就是这个分布的 可是线段树的节点个数是O(n)的 这个的解显然应该是f(n)=O(n)在此表示歉意 咱所知道的字符串算法 Pascal的Pos函数 Hash哈希 Kmp和扩展Kmp Trie树 AC自动机 后缀树,后缀数组(SA),后缀自动机(SAM)Manacher算法 乱搞 最近新出来的:回文自动机(PAM)(太弱不会)。Hash哈希 Hash应该都知道 常用的Hash函数?首先直接把每一个字符的ASCII值加起来作为Hash值不取模的情况很容易冲突 常用的Hash,自己设一个X进
3、制(X=你的字符集的大小-1,比如大写字母有26个字母,字符集大小为26)然后咱们就有 Hash=Si*X(i-1)假设字符串长度为s,这个就可以在O(s)的时间内算出来。显然如果存的下最后的Hash值的话,每一个字符串的Hash值必定不相同。Q:为什么?实际上这种计算方法,每个字符串都是X进制下的一个数,而Hash值就是这个X进制的数转十进制的值,由于X进制的数互不相同,显然Hash值,即十进制的数也互不相同。Q:那如果字符串长度过大,以致会爆怎么办?取个模呗 Q:那如果两个字符串不同Hash值取某个模最后相同怎么办?取多个模呗如果多个模的情况下都相同那么就是同一个字符串。Q:如果取多个模都
4、相同呢?首先,这个模是你自己定的,所以一般数据是没办法全部卡的。接着,由中国剩余定理,只要取到的每个模足够大,那么最后也可以保证一定范围内的Hash值是一定的。Q:中国剩余定理是什么?以后讲数学的时候会讲吧顺便可以百度_(:)_ 除了这种Hash以外,字符串Hash也有很多其他的版本,比如ELFhash(黑书上的)据说这个的效果比上面的还好,咱没试过_(:)_ Function ELFhash(var s:string):integer;Var g,h,i:longint;Begin h:=0;for i:=1 to length(s)do begin h:=h shl 4+Ord(Si);g
5、:=h and$f0000000($是十六进制)if g0 then h:=h xor(g shr 24);h:=h and(not g);end;ELFhash:=h mod M;End;Bzoj1014 JSOI2008 火星人火星人最近研究了一种操作:求一个字串两个后缀的公共前缀。比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号:1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x,y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串,两个字
6、串的公共前缀的长度。比方说,LCQ(1,7)=5,LCQ(2,10)=1,LCQ(4,7)=0 在研究LCQ函数的过程中,火星人发现了这样的一个关联:如果把该字符串的所有后缀排好序,就可以很快地求出LCQ函数的值;同样,如果求出了LCQ函数的值,也可以很快地将该字符串的后缀排好序。尽管火星人聪明地找到了求取LCQ函数的快速算法,但不甘心认输的地球人又给火星人出了个难题:在求取LCQ函数的同时,还可以改变字符串本身。具体地说,可以更改字符串中某一个字符的值,也可以在字符串中的某一个位置插入一个字符。地球人想考验一下,在如此复杂的问题中,火星人是否还能够做到很快地求取LCQ函数的值。字符串长度始终
7、=105,操作数=104 题目是什么意思?一般先化成裸题。LCP是最长公共前缀,现给出一个字符串S,支持以下操作:1 询问 LCP(x,y),也就是原字符串从x开始的字符串和从y开始的字符串最长的公共前缀 2 修改,修改原S的一个字符 3 添加,在S的第X个字符后面添加一个字符。这个有什么做法?也是可以把问题分开来考虑,比如,怎么快速求LCP?Hash?考虑使用Hash来做 实际上这里的LCP(x,y)的x,y所代表的字符串都是S的后缀 考虑每一个后缀Suffixi,就是从S的第i个字符开始的后缀,它的Hash值就是Hashi=Si+Si+1*26+Si+2*262.然后Suffixi的某个前
8、缀Si.j的Hash值怎么算?Hash=Hashi-Hashj*26(j-i+1)预处理出所有后缀的Hashi以及26k的话 也就是说咱们能够O(1)地求出每一个后缀的某个前缀的Hash值。之前又提到过一点:对于两个相同的字符串,他们的Hash值相同,取模之后也相同。对于两个不同的字符串,他们的Hash值不相同,但取模之后可能相同,模的数越大,同时取不同的模,最后相同的可能性越小。以这两点作为依据,咱们可以这样子做。对于询问后缀X与Y的询问,二分答案,即LCP的长度L,然后O(1)求出这个长度为L的前缀的Hash值,取不同的模,如果不同的模之后都相同,则可认为这两个长度为L的字符串相同,二分答
9、案区间上移,否则则认为不同,二分答案区间下移。这样做的复杂度是O(logS)一次,S为字符串的长度。但是对于修改操作,咱们该怎么做?咱们可以发现,修改了字符Si,那么受到影响的就是它前面的所有字符的Hash值,对于前面来说这个改动比较大 而添加字符对于所有的Hash值,都要重算 这怎么做啊,这没法做啊 实际上还是可以做的咱们以原字符串的顺序建立平衡树,每个节点i维护一个信息,就是它为根的子树所构成的字符串的Hash值和它为根的子树的大小size。那么递推式?Hashfa=Hashlson+sfa*26(Sizelson)+Hashrson*26(Sizelson+1)然后这样子就可以做了每一次
10、把一个后缀全部弄到一棵子树里面,然后它的Hash值就是根节点的那个Hash值。这个得用Splay来做 对于修改,直接在子树上修改,然后再往根节点一路走,修改沿途的节点的Hash值。对于添加,直接Splay添加节点,然后往根节点走,每个节点的size+1,Hash值也更新。Splay一次的复杂度是O(logS),所以一次的复杂度是O(logS*logS),假设询问q次,总复杂度就是O(qlogS*logS)P党Splay比较吃力,咱blog有(别人的)AC代码,实在A不了可以去看一看。Hash的实现:2行即可(不算上预处理)上面所提到的Hash能够在O(1)的时间判断两个串是否相同(如果预处理相
11、应的Hash值)。然后Hash不仅仅只可用于字符串,还可以用于某些状态的压缩以及O(1)的查找。比如上一次某道求某个数全部排列模m=0的数的个数的数位dp的,咱们暴力枚举一半的排列a,然后将另一半的排列模m的值转Hash,然后对于排列a,可以计算出为了模m=0另一半所需要的模值,然后O(1)可处理询问。还比如广搜,为了判断某个状态之前是否搜过,也可以设计一个函数做成Hash值。这些都是常见的运用。接着提到的是字符串匹配问题给你一个字符串S,一个字符串P,求P在S中出现了几次。S长度为n,P长度为m。保证m=n咱们所知道的算法1.暴力算法,pos()+delete()以上是检验这题是否是水题的标
12、准2.Rabin-Karp算法。这是什么鬼?实际上就是刚才讲的Hash咱们对字符串P,可以用刚才X进制的Hash函数,然后对于串P咱们有个Hash函数u,对于S的每个长度为m的子串,计算出一个Hash函数,总共有n-m+1个Hash函数,将它们和P的Hash函数u比较即可。然后计算S的n-m+1个Hash函数可以递推。递推式?(假设字符集大小为x)复杂度?O(n-m+1)。(还可以推广到二维平面的字符串匹配!)这么好的算法,为什么咱们竟然不知道?因为这里的Hash是取模的,取模之后有可能相同,而咱们这里要求的算法是100%正确,也就是说精确匹配,如果P和某个的Hash值不同显然无视,可是如果相
13、同的话还得从头比较。(因为从取模的Hash值不能100%确定某个串一定等于另一个)这样的话最坏n-m+1个都要比较,比较一次O(m),复杂度O(m(n-m+1)。这个算法最坏复杂度和暴力差不多但是期望情况很好。3.有限状态自动机匹配(这个后面ppt会提到,预计下次讲了)这个的复杂度,设字符集大小为,那么复杂度建立字符串P的自动机O(m),匹配O(n)。好处是自动机建立好之后,可以同时求多个串S中是否出现P。4.Knuth-Morris-Pratt算法 也就是所说的KMP算法。1)KMP算法的原理?2)KMP算法复杂度的证明?3)能随手敲一个KMP吗?KMP算法其实不难理解。设这里有个S串一部分
14、为ababaab,P串为ababaca,匹配到第六个字符的时候失效,这个时候咱们就想尽量利用已经匹配到的信息。考虑暴力做法是怎么样的。暴力的做法就是右移一位,然后再从头比较,但是咱们通过之前的匹配知道这里是不可能有匹配的。因为已经匹配的部分ababaa的babaa的这个后缀和ababaa这个的公共前缀为0.所以这里还去匹配是不理智的。咱们发现这里的信息所涉及的串好像只跟P有关 而这个暴力的过程,实际上就是拿P的第i个后缀和它的前缀继续匹配。而如果这个后缀能够匹配P的某个前缀,那么它就能继续在失配的那个地方匹配下去。实际上就是求P已经匹配的串p1.i的最大后缀,使得它是p1.i的公共前缀!而这个
15、东西是只和P字符串有关 比如ababaa字符串,它的p1.5的最大后缀是3.5也就是aba,它和ababaa的前缀p1.3匹配。这个时候咱们直接将P移动到S的ababaa的第二个a处即可。这个时候已经有3个字符被匹配了。所以咱们只要求P的每个前缀的最长的相同后缀就可以了。设这个后缀的长度是next nexti的含义就是p1.i这个字符串的能够匹配前缀的最大后缀的长度。几个小练习来理解.abbabba的next4=?next6=?next4=1,next6=3.这个next函数理解了之后,考虑nextnext的含义?nexti是p1.i这个字符串能够匹配前缀的最大后缀的长度,也就是说p1.i里面
16、p1.nexti=pi-nexti+1.i 而且这个是最长的。那么nextnexti就是p1.nexti这个字符串的能够匹配前缀的最大后缀的长度,又由于p1.nexti=pi-nexti+1.i,所以这个可以理解为:能够匹配p1.nexti前缀的pi-nexti+1.i的最大后缀的长度 实际上这个又等价于匹配p1.i前缀的p1.i的第二大后缀。也就是说nextnexti表示的就是能够匹配p1.i的前缀的第二大后缀的长度。那么nextnextnexti?表示的就是能够匹配p1.i的前缀的第三大后缀的长度。以此类推 现在考虑求nexti,假设已经知道next1,next2,next3,nexti-
17、1。因为nexti-1表示的是p1.i-1的匹配前缀的最长后缀。那么如果pnexti-1+1=pi的话,那么显然p1.i的匹配的最长前缀就是p1.nexti-1+1了。这个时候nexti=nexti-1+1;如果pnexti-1+1pi。咱们也没关系。nexti表示的是p1.i-1匹配前缀的最长后缀,咱们可以继续去找第二长,第三长后缀继续去匹配。怎么做?之前提到了,假设第K长的后缀的长度是u,那么第K+1长的后缀的长度就是nextu 枚举第K长后缀,判断其对应前缀+1的字符是不是si,如果是的话,这个就是p1.i的匹配的最长前缀了。某个实现代码如下:next1:=1;For i:=2 to m
18、 do Begin j:=nexti-1;其实不需要写这句话,因为这个过程倒数第二行已经有了这句话,这里标上是为了强调 while(j0)and(sj+1si)do j:=nextj;if(sj+1=si)inc(j);nexti:=j;End;代码量也是极短的 以上是预处理。接下来是KMP算法的匹配。实际上比预处理简单多了。假设匹配两个字符,匹配得上,两个都+1,这个显然。考虑匹配不上,假设这个时候是p1.i已经匹配,pi+1和sx失配,咱们只需要沿着nexti走,然后继续匹配即可,如果走到0了还是没能匹配,那么sx无论如何都匹配不了,接下来继续匹配sx+1和p1。考虑P:abbabba S
19、:aaababbababbabbaba 的匹配过程。最后就是复杂度证明了 先证明预处理的复杂度是线性的,也就是O(m)的 考虑有哪些操作 For i:=2 to m do while(j0)and(sj+1si)j=nextj if(sj+1=si)inc(j)nexti=j 咱们发现复杂度在于j的变化。考虑j的增加,j最多增加m次,每次都加1。考虑j的减少,由于j最后非负,j减少肯定不超过m,考虑最坏情况j每次只减少1,那么最后也只减少m次,所以复杂度是O(m)线性的。Smartoj p1848 统计单词数 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还
20、能统计出特定单词在文章中出现的次数。现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置。!注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相同(参见样例 1),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例 2)。输出单词出现的次数和第一次出现的位置(-1代表未出现)单词的位置从0开始 To To to be or not to be is a question 2 0(出现2次,第一次出现在0处)to Did the Ottoman Empire lose its
21、 power at that time -1 单词长度=10 文章长度=106 这道题不像普通的匹配,必须要求原文章的对应字符是一个独立的单词。然而这并没有什么 因为咱们可以找出一个单词在原文章出现的所有位置,所以只需要每找到一个,判断他是否是一个独立的单词就可以了。判断是否是独立的单词,其实就是看这个字符串前面和后面是否是空格就可以了一个独立的单词按照题目意思,必然是前后都是空格 问题解决。CH HSYOI2015 Round2 E.字符串与KMP 给你一个n=106的字符串,求该字符串的最小循环节。循环节就是该字符串可由该循环节重复得到。比如abcabc的最小循环节是3,aaaaa的最小循
22、环节是1.要做这道题请加入CH上华师一附中的小组,无需审核。求一个字符串的循环节咱们和这道题的标题相联系很容易想到KMP算法。但是KMP算法不是求字符串P和S的匹配么?这里才一个字符串?考虑next的含义,nexti是p1.i的匹配前缀的最大后缀。设字符串P长度为n,那么nextn含义?P1.n的匹配前缀的最大后缀。如果P是由一个最小循环节构成的串,那么咱们能够知道,pnextn+1n就是它的最小循环节。为什么?假设有K个最小循环节,那么显然P1.n的最大后缀就是后K-1个循环节构成的后缀。假设有更长的后缀,可以通过证明最小循环节内部的字符全部右移X位不等于原字符得证。所以算法就是,求这个字符
23、串的next,然后答案就是n-nextn;Noi2014 动物园 题目大意:给定字符串S,定义num,numi表示的是S的前缀S1.i的能够匹配前缀的后缀的个数,且要求该后缀不能与匹配的前缀相重叠。求(1+numi)S长度n=106 一组数据可能有多个(T个)字符串要求该值,T=10 考虑next的含义,nexti正是S1.i匹配前缀的最大后缀,而nextnexti就是第二大,以此类推。那么对于每个i,咱们只要找到第一个nextnext.,满足nextnext.=i/2,那么这之后的都满足答案。咱们考虑每个i走多少次走到尽头,设这个次数为disti,那么咱们就是要找到一个0=j=disti,使
24、得它的长度小于等于i/2,显然这是单增的所以直接二分就可以了,复杂度O(logN)一次。最后的复杂度就是O(nlognT),可以过。实际上考虑inexti看作一条边的话,每个位置看作一个点的话,这显然就是一个森林。所以上面的二分的方法其实就是树上路径的二分。出题者当时愤恨地说,没能卡掉logN真是可惜。这真是一个悲(Xi)伤(Gan)的故事 也就是说这里还有更好的做法?咱们考虑定义一个新的数组Next,Next数组类似next,Nexti表示S1.i中匹配前缀的最大后缀,且这个后缀和前缀不重合。考虑已经求出了Next1,Next2.Nexti-1,现在要求Nexti,咱们类似next的做法,先
25、令j=Nexti-1,然后考虑Sj+1=Si?然后还要判断是否超界,如果超界,贪心的咱们就继续往nextj走即可。这样的复杂度和Kmp是一样的是O(n)的。Q:为什么不在求next的时候一起求Next?因为求Next的时候如果在求Kmp的时候回去找,实际上就相当于每一次都暴力从某个节点沿着树往根走,这和暴力没啥区别。而后面的类似Kmp的Next的求法则是从上一次Next作为起点的,可以用类似Kmp复杂度证明的方法证明它也是线性的(这题可见掌握Kmp算法的原理和复杂度的证明有多么重要)Smartoj p2168 Clover 9外星人 外星人有n只眼睛,排成一排,从左到右标号为1 to n.他睡
展开阅读全文