《广东省汕头市金山中学高中信息技术竞赛班数据结构专项培训教程04串教案(共9页).docx》由会员分享,可在线阅读,更多相关《广东省汕头市金山中学高中信息技术竞赛班数据结构专项培训教程04串教案(共9页).docx(9页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、精选优质文档-倾情为你奉上4 串4.1 串的匹配子串的定位操作称为串的模式匹配,是各种串处理中最重要的操作。在主字符串S中查找模式字符串P,若在主串中找到等于模式串的子串,称为匹配成功,返回与模式串第一个相等的字符在主串中的序号;若匹配不成功,则返回0。4.1.1 串的简单匹配串的简单匹配,基本思想是:从主串的第一个字符起和模式串的第一个字符比较,若相等,则继续逐个比较后续的字符,否则从主串的第二个字符起再重新和模式串的字符比较。依此类推,直至模式串的每个字符依次和主串中的一个连续的字符序列相等,则为匹配成功.【例4-1-1】: 主串:a b a b c a b c a c b a b匹配串:
2、a b c a c i =3第一趟匹配: a b a b c a b c a c b a b a b c j =3 i=2第二趟匹配: a b a b c a b c a c b a b a j=1 i=7第三趟匹配: a b a b c a b c a c b a b a b c a c j=5 i=4第四趟匹配: a b a b c a b c a c b a b a j=1 i=5第五趟匹配: a b a b c a b c a c b a b a j=1 i=11第六趟匹配: a b a b c a b c a c b a b a b c a c j=6这种算法易于理解,在某些场合效率
3、也较高。但当主串为0000001,模式串为时,由于模式串中前7各字符均为0,主串中前50各字符均为0,每趟比较都在模式串的最后一个字符出现不等,此时需将指针i回溯到i-6的位置上,并从模式的第一个字符开始重新比较。直到匹配成功,指针i需回溯43次。这经常出现在主串中存在多个子串和模式串部分匹配的情况下,例如01串(字符串由0、1组成)。4.1.2 串的KMP匹配算法这种改进的算法是由D.E.Knuth、V.R.Pratt和J.H.Morris三人同时发现的,所以称为KMP算法。(一)KMP算法的基本思路KMP算法每当一趟匹配过程中发现字符不等时,不需回溯i指针,而是利用已经得到的部分匹配的结果
4、将模式串向右滑动尽可能远的一段距离后,继续进行比较。先回顾简单匹配的算法,从例4-1-1可以看出,在第三趟匹配中,当i=7、j=5字符比较不等时,又从i=4、j=1重新比较。而在i=4和j=1,i=5和j=1,以及i=6和j=1这三次比较都是不必要的。因为从第三趟部分匹配的结果可以看出,主串中第4、5、6个字符必然是b、c、a(即模式串中第2、3、4个字符)。因为模式串中第一个字符是a,因为它无需和这三个字符进行比较,所以仅需将模式串向右滑动三个字符的位置进行比较。同理,在第一趟匹配中出现字符不等时,仅需将模式串向右移动2个字符的位置继续进行i=3、j=1时的字符比较。由此,整个过程指针i没有
5、回溯,如下所示。i=3第一趟匹配:a b a b c a b c a c b a ba b cj=3i=7第二趟匹配:a b a b c a b c a c b a ba b c a cj=5i=11第三趟匹配:a b a b c a b c a c b a ba b c a cj=6KMP算法的基本思想是:在匹配过程中,当 SiPj 时,应在模式串P的开头和主串S紧靠i之前找到相等的最大子串,子串长度为k -1,如图所示:然后将模式串向右滑动,比较Si和Pk是否相等。对于KMP算法,需要解决的问题首先是:当匹配过程产生失配,模式串向右滑动可行多远?换句话说,当主串中第i个字符与模式串中第j个
6、字符失配(即不相等)时,主串中第i个字符应与模式串中哪个字符再比较?(二)求证k仅与模式串相关设主串为S,模式串为P。假设当主串中第i个字符与模式串中第j个字符失配时,主串的第i个字符应与模式串的第k个字符继续比较,则模式串中前j个字符必须满足下列关系:P1P2.Pk-1Si - k+1Si - k+2.Si-1 (1) 匹配串P的前k-1个字符与主串中第i个字符前的k-1个字符相等而已经得到部分匹配的结果是: Pj-k+1Pj-k+2.Pj-1Si-k+1Si-k+2.Si-1 (2) 匹配串P第j个字符前的k-1个字符与主串中第i个字符前的k-1个字符相等由(1)和(2),可以推出下式:P
7、1P2.Pk-1Pj-k+1Pj-k+2.Pj-1即模式串中前k-1个字符与第j-k+1到j-1个字符相等,即k仅与模式串有关,与主串无关。(三)next数组因此,我们可以设next数组,令nextj=k,则nextj表明当模式中第j个字符与主串相应字符失配时,主串中该字符重新与模式串中进行比较的字符的位置。Next数组的定义: 0 当 j=1时 nextj= Max k | 1kj 且 p1.pk-1=pj-k+1.pj-1 当此集合不空时1 其它情况 【例4.1.2_1】 j1 2 3 4 5 6 7 8模式串next j a b a a b c a c0 1 1 2 2 3 1 2Nex
8、t数组怎样具体求得,我们这里先放一下,先看看在设了next数组后KMP匹配的算法,这可能将更有利于理解。(四)KMP算法匹配可如下进行: 指针i和j分别指示主串和模式串中正待比较的字符,令i和j的初值皆为1。 若在匹配过程中si = pi ,则i和j分别增1,否则j再退到下一个next值的位置, 依此类推,直至下列可能: 一种是j退到某个next(next next . next j )值时字符比较相等,则指针各自增1继续进行匹配(模式串滑动);另一种是j退到next值为0(即模式的第一个字符失配),则此时需将模式串继续向右滑动一个位置,从主串的下一个字符si+1起和模式串重新开始匹配。算法如
9、下:function KMP:integer;. 假设已求出next数组begin i:=1; j:=1; 指针初始化 while (i=s.length) and (jp.length then KMP:=i-p.length 匹配成功 else KMP:=0;end;(五)求next数组的算法从上述讨论已知,next数组的值仅与模式串本身有关,而与相匹配的主 串无关,我们可以根据模式串,从分析其定义出发,用递推的方法求得next数组的值。由定义知: next 1 = 0设已求得 next j = k ,求next j+1 = ? 有两种情况:1若Pk = Pj ,则表明在模式串中:P1.P
10、kPj - k+1.Pj就是说 next j+1 = k+1 ,即:next j+1 = next j +12若PkPj,则表明在模式串中:P1.PkPj - k+1.Pj此时如何处理?procedure next; var i , j , k :integer; begin next 1 := 0;k := 0;for j := 1 to p_length -1 do p_length为模式串P的长度 begin if (k = 0) or (Pj = Pk) then begin endelse begin end; end; end; 参考答案: k := k+1;next j+1 :=
11、 k; repeat k := next k; until(k=0)or(Pj=Pk); k := k+1; next j+1 := k; 求next数组程序2:procedure next; var j , k :integer; begin j := 1; k := 0; next1 := 0; while j p_length do if(k=0)or(Pj=Pk) then begin j := j+1; k := k+1; nextj := k; end else k := nextk; end; 另一种求next数组的算法: procedure next; readln (p);
12、next1:= 0; for j:=2 to p_length do begin k := j-1; repeat k:=k-1; until copy(p,1,k) = copy(p,j-k,k); nextj := k+1; end; end; (六)进一步优化:前面定义的next函数在某些情况下尚有缺陷,例如:模式串P=aaaab和主串S=aaabaaaab匹配当i=4,j=4,S4P4时,由nextj的指示,模式串向右移,S4还要与P3、P2、P1继续比较。实际上,因为模式串中第1、2、3个字符和第4个字符都相等,没必要再和S4相比较,可将模式串直接向右滑动4个字符,进行i=5、j=1
13、时的比较。为了克服这种不必要的重复比较,对求next的算法进行改进,其基本思想是:在求得j点的k值后,在判断Pk和Pj是否相等,若相等则把nextvalk值送nextvalj中,否则把原来的k值存入nextvalj中。表中的nextvalj就是改进后的值。j 1 2 3 4 5 6 7 8 9 10 11模式串P a b c a b c a b b a cnextj 0 1 1 1 2 3 4 5 6 1 2nextvalj 0 1 1 0 1 1 0 1 6 0 2算法为: procedure next2; var j,k :integer; begin j:= 1; k := 0; nex
14、tval1 := 0; while j0)and(sk = pj)do begin j := j - 1; k := k - 1; end; if j0 then i := i + nextb si ; until (j = 0)or(j n); if j = 0 then BM_match := i - m + 1 else BM_match := 0; end;4.1.3 串的广义匹配设主串S和模式串P,按模式串中字符顺序在主串中顺序找到但不一定连续与模式串相同的字符序列,称之为广义匹配。广义匹配具有许多的用途,如数据库的模糊查询等。 例如: 主串S= a c d a c b e m 模式
15、串P=d c b S: a c d a c b e m P: d c b 显然有 S3S5S6P1P2P3参考算法如下,它主要适用于ASCII码字符和汉字字符。 program gypp; var p , s : string; i , j , k : integer; d : array 1 . . 260 of integer;Begin write ( P: ); readln (p); write ( S: ); readln (S); i := 1; j := 0; while i=length(s) do begin if pj+1=si then begin j := j+1;
16、dj := i; i := i+1; end else i := i+1; end; if j=0 then writeln (No find) else for k:=1 to j do write (dk:3);End.【综合练习】1、 求回文数若一个数(首位不为零)从左向右读与从右向左读都是一样,则称为回文数。有一种求回文数的方法:例如,给定一个十进制整数56,将56加65(即把56从右向左读),得到的121是一个回文数;又如,对于十进制数87,按以上方法用4步可以得到回文数4884。step1: 87+78=165 step2:=165+561=726step3: 726+627=1353 step4:=1353+3531=4884给定一个N进制数m,(2=N=16, m的位数上限为20),求最少经过几步可以得到回文数。如果在30步以内不能得到回文数,则输出impossible。输入:只有2个整数 N 和m 。输出:步数/impossible输入样例:9 87输出样例:62、 构造字串生成长度为n的字串,其字符从26个大写英文字母的前p个字母中选取,使得没有相邻的子序列相等。例如: p=3 , n=5 时:ABCBA满足条件,ABCBC不满足条件。输入: n p输出:满足条件的字串专心-专注-专业