ImageVerifierCode 换一换
格式:DOCX , 页数:14 ,大小:117.04KB ,
资源ID:10925258      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10925258.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(KMP串匹配并行算法的MPI实现.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

KMP串匹配并行算法的MPI实现.docx

1、KMP串匹配并行算法的MPI实现KMP串匹配的MPI实现一、简单匹配算法KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法。简单匹配算法的时间复杂度为O(m*n);KMP匹配算法。可以证明它的时间复杂度为O(m+n).。先来看一个简单匹配算法的函数:int Index_BF ( char S , char T , int pos ) /* 若串 S 中从第pos(S 的下标0posStrLength(S)个字符起存在和串 T 相同的子串,则称匹配成功,返回第一个这样的子串在串 S 中的下标,否则返回 -1*/int i = pos, j = 0; while ( Si+j

2、 != 0& Tj != 0) if ( Si+j = Tj ) j +; / 继续比较后一字符else i +; j = 0; / 重新开始新的一轮匹配if ( Tj = 0) return i; / 匹配成功 返回下标else return -1; / 串S中(第pos个字符起)不存在和串T相同的子串 / Index_BF此算法的思想是直截了当的:将主串S中某个位置i起始的子串和模式串T相比较。即从 j=0 起比较 Si+j 与 Tj,若相等,则在主串 S 中存在以 i 为起始位置匹配成功的可能性,继续往后比较( j逐步增1 ),直至与T串中最后一个字符相等为止,否则改从S串的下一个字符起

3、重新开始进行下一轮的匹配,即将串T向后滑动一位,即 i 增1,而 j 退回至0,重新开始新一轮的匹配。例如:在串S=”abcabcabdabba”中查找T=” abcabd”(我们可以假设从下标0开始):先是比较S0和T0是否相等,然后比较S1 和T1是否相等我们发现一直比较到S5 和T5才不等。如图:当这样一个失配发生时,T下标必须回溯到开始,S下标回溯的长度与T相同,然后S下标增1,然后再次比较。如图:这次立刻发生了失配,T下标又回溯到开始,S下标增1,然后再次比较。如图:又一次发生了失配,所以T下标又回溯到开始,S下标增1,然后再次比较。这次T中的所有字符都和S中相应的字符匹配了。函数返

4、回T在S中的起始下标3。如图:二、 KMP算法2.1 KMP算法原理给定两个串S=“S0S1.Sn-1” 和T=“T0T1Tm-1”,在主串S中寻找子串T的过程称为模式匹配,T称为模式串,若匹配成功,则返回模式串T在主串S中第一次出现的位置,若匹配失败,则返回一1。KMP算法可以在O(m+n)的时间数量级完成串的模式匹配操作,其改进在于:每当一趟匹配过程中出现字符比较不等时,就利用已经得到的“部分匹配”的结果将模式串“向右滑动”尽可能远的一段距离后,继续进行比较。为了实现改进算法,需要解决下述问题:当匹配过程中产生“失配”时,模式串“向右滑动”可行的距离有多远?换句话说,当主串中第i个字符与模

5、式串中第j个字符“失配”时,主串中第i个字符应与模式串中哪个字符再进行比较?假设当“失配”时,模式串向右滑动的距离为k,则模式串中每个字符都对应一个k值,这个k值只依赖于模式串本身字符序列的构成,而与主串无关,用nextj表示与Tj相对应的k值(Ojm-1),则next定义如下:Nextj=-1 当j=0;Nextj=maxk 当k-1kj 且T0Tk-1=Tj-kTj-1Nextj=0 其他假设模式串T=“abaabaac ”,根据公式计算next值。j01234567TabaabaacNext-10011234KMP算法的基本思想:在求得模式串的next值之后,匹配可按如下步骤进行,假设i

6、和j分别指示主串和模式串中正待比较的字符,i和j的初值均为0。若在匹配过程中Si= Tj,则 i和j分别增1,继续进行比较;否则,i不变,而j退回到nextj的位置继续比较,如此反复,直到出现下列两种可能:(1) 当j退回到某个n e x t 值时字符比较相等,则i和j分别增1,继续进行匹配;(2) 当j退回到1,即模式串的第一个字符“失配”,则将主串向右滑动一个位置,使j=0,即从主串下一个字符Si +1起和模式串重新开始匹配。 例: 若主串S=“ a c a b a a b c a b a a b a a c b c ” , 模式串T =“a b a a b a a c ” , 则匹配过程

7、如下: 第一趟: 主串: a c a b a a b c a b a a b a a c b c ( i = 0,1)模式串: a b ( j =0,1) 此时Next1 =0, 因而i不变 j =Nextj = 0;第二趟: 主串: a c a b a a b c a b a a b a a c b c ( i =1 ) 模式串: a ( j = 0 ) 此时 n e x t 0 = 1 , 因而 i +, j = 0 第三趟: 主串: a c a b a a b c a b a a b a a c b c ( i =2 ,3,4 ,5,6 ,7 ) 模式串: a b a a b a ( j

8、 = 0,1,2,3,4,5 ) 此时Next 5 = 2 ,因而i不变,j = Next j = 2 第四趟: 主串: a c a b a a b c a b a a b a a c b c ( i = 7 ) 模式串:( a b ) a ( j = 2 ) 此时Next 2 = O,因而i 不变,j = Nextj= 0 第五趟: 主串: a c a b a a b c a b a a b a a c b c ( i = 7 ) 模式串: a ( j = 0 ) 此时 n e x t 0 = 1,因而 i +,j = 0 第六趟 :主串: a c a b a a b c a b a a b

9、 a a c b c ( i =8,9,10,11,12,13,14,15) 模式串: a b a a b a a c ( j =0,1,2,3,4,5,6,7,8) 此时j = 8 ,匹配成功。 从例子可以看出,在第三趟,模式串中第5个字符与主串字符比较失配时,主串指针i不变,继续与模式串中第2个字符比较,而T5=T2=a,匹配必然失败,显然此次比较是多余的,这说明KMP算法中给出的next的求值方法不是最优的,因此,对算法的优化改进就是对next的求值方法的改进。2.2 KMP算法实现1、假设以i和j分别指示正文t和模式p中正等待比较的字符,令i、j的初值为0;若在匹配的过程中ti =pj

10、,则i与j分别加1;否则i不变,而j退到nextj的位置继续比较(即j=nextj),r若相等,则指针各自增加1;否则j再退到下一个nextj值位置,依次类推,直到下列两种可能之一出现。(1) j退到某个next值(next.nextj.)时,ti = =pj成立,则i,j指针各自加1后继续比较。(2) j退到-1(即模式的第一个字符“失配),此时需要将正文的指针i向右滑动一个位置,即从正文的下一个字符ti+1起和模式p重新从头开始比较。void getnext(string p ,int *next)int len = p.length(); int k = 0; nextk=-1; /ne

11、xt0=-1 int j = -1;while(klen) if(j= -1 | pj = pk) k+;j+;nextk = j; else j = nextj; cout next数组:;for(int x=0;xlen;x+) cout nextx ;2、求next:next0= -1,j假设next0,nexti,.nexti的均已求出,现在要求nexti+1的值。由于在求解nexti时已经得到pi之前最长真前缀和真后缀匹配的长度,设其值为j,即:nexti = j ; 如果此时进一步有pj = = pi,则pi+1之前最长真前缀的和真后缀匹配的长度就为j+1,且nexti+1=j+1

12、;反之,若pj!=pi,注意到,求pi+1之前的最长真前缀和真后缀匹配问题本质上仍然是一个模式匹配问题,只是在这里模式和正文都是同一个串p而已。因此pj!=pi时,应检查pnextj与pi是否相等,若相等,则nexti+1 =nextj+1,若仍然不想等,再取pnextnextj与pi进行比较,直到要将p-1与pi进行比较为止,此时nexti+1 =0。void getnext(string p ,int *next)int len = p.length(); int k = 0; nextk=-1; /next0=-1 int j = -1; while(klen) if(j= -1 | p

13、j = pk) k+;j+; nextk = j; else j = nextj; cout next数组:;for(int n=0;np.length();n+) cout nextn S0 != S1,S1 != S2,所以S1!=T0,S2!=T0.还是从理论上间接比较了。KMP算法时间复杂度的计算:while循环使得执行次数出现了不确定因素。我们将用到时间复杂度的摊还分析中的主要策略,简单地说就是通过观察某一个变量或函数值的变化来对零散的、杂乱的、不规则的执行次数进行累计。KMP的时间复杂度分析可谓摊还分析的典型。我们从上述程序的j 值入手。每一次执行while循环都会使j减小(但不能

14、减成负的),而另外的改变j值的地方只有第五行。每次执行了这一行,j都只能加1;因此,整个过程中j最多加了n个1。于是,j最多只有n次减小的机会(j值减小的次数当然不能超过n,因为j永远是非负整数)。这告诉我们,while循环总共最多执行了n次。按照摊还分析的说法,平摊到每次for循环中后,一次for循环的复杂度为O(1)。整个过程显然是O(n)的。这样的分析对于后面P数组预处理的过程同样有效,同样可以得到预处理过程的复杂度为O(m)。其实,KMP的预处理本身就是一个T串“自我匹配”的过程三、改进的KMP算法3.1 算法的基本思想虽然模式匹配KMP算法的引入避免了算法中频繁的回溯,普遍提高了模式

15、匹配的工作效率,但是经过分析,对KMP算法扫描部分还可做进一步的改进,下面介绍改进KMP算法的基本思想。基本思想:每当某趟匹配失败时,i指针不必回溯,而是利用己经得到的部分匹配结果,看看是否有必要将i的值进行调整,然后再将模式向右滑动若干位置后继续比较。改进的 KMP 算法中的i 不是保持不变, 而是增加了, 这就意味着加快了模式匹配的进度。针对KMP算法的不足,下面给出新的next计算公式 : Nextj= 1 当j=0;Nextj= 1 当 k-1kj且 T0Tk-1 =Tj-kTj-1且 Tk=TjNextj= maxk 当 k-1kj且 T0Tk-1 =Tj-kTj-1且 Tk!=Tj

16、Nextj=0 其他公式(2)是主要对公式(1)的第二种情况给出了改进,从而减少了多余的比较次数。对模式串T= “a b a a b a a c ”,根据公式( 2 )计算n e x t值。j01234567模式串abaabaacNext-10-11-1-1-14根据改进的next值,上例的匹配过程如下: 第一趟: 主串:a e a b a a b c a b a a b a a e b c ( i = 0,1 ) 模式串: a b ( j = 0,1 ) 此时next1 =0,因而i不变,j = next j = 0; 第二趟: 主串: a c a b a a b c a b a a b a

17、 a e b c ( i = 1 ) 模式串:a ( j=0 ) 此时n e x t 0 =一l,因而i +,j =0第三趟: 主串:a c a b a a b c a b a a b a a e b c ( i=2,3,4,5,6,7) 馘 串: a b a a b a ( j = 0,1,2,3,4,5) 此时n e x t 5 =一1 ,因而i + j = 0第四趟: 主串: a c a b a a b c a b a a b a a e b e (i=8,9,10,11,12,13,14,15) 模式串: a b a a b a a c ( j =0,1,2,3,4,5,6,7,8)

18、此时j = 8 ,匹配成功。3.2 KMP改进算法的实现void getnext(char *t,int *next) int i,j; int tlen=strlen(t); i=0;j=-1; next0=-1; while(itlen) if(j=-1 | ti=tj) i+;j+; if(ti=tj) nexti=-1; else nexti=j; else j=nextj; int kmp_match(char *s,char *t,int pos) int i,j,slen,tlen; int *next=(int *)malloc(sizeof(int); slen=strlen

19、(s); tlen=strlen(t); *next=tlen; getnext(t,next); i=pos; j=0; while(islen & jtlen) if(j=-1 | si=tj) i+;j+; else j=nextj; if(j0)?(myid*n-m):0,tlen,myid); else kmp_match(T,P,next,(myid*n-m0)?(myid*n-m):0,(myid+1)*n,myid); MPI_Finalize(); free(next); return 0;4.3 运行结果显示 在192.168.150.217上:编译: 运行: 首先运行gen_ped生成模式串: 之后可以使用命令mpirun np SIZE kmp m n来运行该串匹配程序: 存储在pattern.dat中的模式串为:nwn 存储在match_result中的匹配结果为: 结论本文针对模式匹配算法中KMP模式匹配算法在匹配过程中存在的一些不足进行了改进,给出了一种改进的KMP改进算法的设计思想、原理,并对其进行了详细的

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1