《KMP 字符串模式匹配算法》教学课例
- 格式:doc
- 大小:975.00 KB
- 文档页数:13
KMP算法是一种字符串匹配算法,用于在一个主串中查找一个模式串的出现位置。
它的核心思想是利用已经匹配过的部分信息,尽量减少不必要的比较。
KMP算法的公式如下:1. 预处理模式串,得到next数组:-初始化next数组,next[0] = -1,next[1] = 0;-从第2个字符开始,依次计算next[i]的值:-如果模式串的前缀和后缀匹配,即pattern[j] == pattern[i-1],则next[i] = j + 1;-如果模式串的前缀和后缀不匹配,即pattern[j] != pattern[i-1],则需要回溯到前一个可能的匹配位置,即j = next[j],直到找到一个匹配位置或者回溯到起始位置;-如果回溯到起始位置仍然没有找到匹配位置,则next[i] = 0。
2. 在主串中查找模式串:-初始化主串指针i = 0,模式串指针j = 0;-依次比较主串和模式串的字符:-如果主串和模式串的字符匹配,即text[i] == pattern[j],则继续比较下一个字符;-如果主串和模式串的字符不匹配,即text[i] != pattern[j],则需要根据next数组回溯模式串的指针j,即j = next[j],直到找到一个匹配位置或者回溯到起始位置;-如果回溯到起始位置仍然没有找到匹配位置,则主串指针i和模式串指针j都向后移动一位,继续比较下一个字符;-如果模式串指针j移动到模式串的末尾,则表示找到了一个匹配位置,返回匹配位置的起始索引;-如果主串指针i移动到主串的末尾,则表示没有找到匹配位置,返回-1。
KMP算法通过预处理模式串得到next数组,利用next数组的信息在匹配过程中尽量减少不必要的比较,提高了匹配效率。
串串(String)又叫做字符串,是一种特殊的线性表的结构,表中每一个元素仅由一个字符组成。
随着计算机的发展,串在文字编辑、词法扫描、符号处理以及定理证明等诸多领域已经得到了越来越广泛的应用。
第一节串的定义和表示1、串的逻辑结构定义串是由零个到任意多个字符组成的一个字符序列。
一般记为:S=’ a1a2a3……a n’(n>=0)其中S为串名,序列a1a2a3……a n为串值,n称为串的长度,我们将n=0的串称为空串(null string)。
串中任意一段连续的字符组成的子序列我们称之为该串的子串,字符在序列中的序号称为该字符在串中的位置。
在描述中,为了区分空串和空格串(s=‘’),我们一般采用来表示空串。
2、串的基本操作串一般包含以下几种基本的常用操作:1、length(S),求S串的长度。
2、delete(S,I,L),将S串从第I位开始删除L位。
3、insert(S,I,T),在S的第I位之前插入串T。
4、str(N,S),将数字N转化为串S。
5、val(S,N,K),将串S转化为数字N;K的作用是当S中含有不为数字的字符时,K记录下其位置,并且S没有被转化为N。
3、串的储存结构一般我们采用以下两种方式保存一个串:1、字符串类型,描述为:const n=串的最大长度type strtype=string[n]这里由于tp的限制,n只能为[1..255]。
在fp或者delphi中,我们还可以使用另外一种类型,描述为:const n=串的最大长度type strtype=qstring[n]这里的n就没有限制了,只要空间允许,开多大都可以。
2、数组来保存,描述为:const n=串的最大长度type strtype=records:array[1..n] of char;len:0..n;end;第二节模式匹配问题与一般的线性表不同,我们一般将串看成一个整体,它有一种特殊的操作——模式匹配。
串的模式匹配算法字符串模式匹配是计算机科学中一种常用的算法。
它是一种检索字符串中特定模式的技术,可以用来在字符串中查找相应的模式,进而完成相应的任务。
字符串模式匹配的基本思想是,用一个模式串pattern去匹配另一个主串text,如果在text中找到和pattern完全匹配的子串,则该子串就是pattern的匹配串。
字符串模式匹配的过程就是在text中搜索所有可能的子串,然后比较它们是否和pattern完全匹配。
字符串模式匹配的算法有很多,其中著名的有暴力匹配算法、KMP算法、BM算法和Sunday算法等。
暴力匹配算法是最简单也是最常用的字符串模式匹配算法,其思想是从主串的某一位置开始,依次比较pattern中每一个字符,如果某个字符不匹配,则从主串的下一位置重新开始匹配。
KMP算法(Knuth-Morris-Pratt算法)是一种更为高效的字符串模式匹配算法,它的特点是利用了已匹配过的字符的信息,使搜索更加有效。
它的实现思想是,在pattern中先建立一个next数组,next数组的值代表pattern中每个字符前面的字符串的最大公共前缀和最大公共后缀的长度,这样可以在主串和模式串匹配失败时,利用next数组跳转到更有可能匹配成功的位置继续搜索,从而提高字符串模式匹配的效率。
BM算法(Boyer-Moore算法)也是一种高效的字符串模式匹配算法,它的实现思想是利用主串中每个字符最后出现的位置信息,以及模式串中每个字符最右出现的位置信息来跳转搜索,从而减少不必要的比较次数,提高搜索效率。
Sunday算法是一种简单而高效的字符串模式匹配算法,它的实现思想是,在主串中搜索时,每次从pattern的最右边开始比较,如果不匹配,则根据主串中下一个字符在pattern中出现的位置,将pattern整体向右移动相应位数,继续比较,这样可以减少不必要的比较次数,提高算法的效率。
字符串模式匹配算法的应用非常广泛,它可以用来查找文本中的关键字,检查一个字符串是否以另一个字符串开头或结尾,查找文本中的模式,查找拼写错误,检查字符串中是否包含特定的字符等。
串的两种模式匹配算法 模式匹配(模范匹配):⼦串在主串中的定位称为模式匹配或串匹配(字符串匹配) 。
模式匹配成功是指在主串S中能够找到模式串T,否则,称模式串T在主串S中不存在。
以下介绍两种常见的模式匹配算法:1. Brute-Force模式匹配算法暴风算法,⼜称暴⼒算法。
算法的核⼼思想如下: 设S为⽬标串,T为模式串,且不妨设: S=“s0s1s2…sn-1” , T=“t0t1t2 …tm-1” 串的匹配实际上是对合法的位置0≦i≦n-m依次将⽬标串中的⼦串s[i…i+m-1]和模式串t[0…m-1]进⾏⽐较:若s[i…i+m-1]=t[0…m-1]:则称从位置i开始的匹配成功,亦称模式t在⽬标s中出现;若s[i…i+m-1]≠t[0…m-1]:从i开始的匹配失败。
位置i称为位移,当s[i…i+m-1]=t[0…m-1]时,i称为有效位移;当s[i…i+m-1] ≠t[0…m-1]时,i称为⽆效位移。
算法实现如下: (笔者偷懒,⽤C#实现,实际上C# String类型已经封装实现了该功能)1public static Int32 IndexOf(String parentStr, String childStr)2 {3 Int32 result = -1;4try5 {6if (parentStr.Length > 1 && childStr.Length > 1)7 {8 Int32 i = 0;9 Int32 j = 0;10while (i < parentStr.Length && j < childStr.Length)11 {12if (parentStr[i] == childStr[j])13 {14 i++;15 j++;16 }17else18 {19 i = i - j + 1;20 j = 0;21 }22 }23if (i < parentStr.Length)24 {25 result = i - j;26 }27 }28 }29catch (Exception)30 {31 result = -1;32 }33return result;34 } 该算法的时间复杂度为O(n*m) ,其中n 、m分别是主串和模式串的长度。
KMP算法的时间复杂度KMP算法是一种字符串匹配算法,它可以在一个主串中高效地查找所有匹配某个模式串的位置。
在计算机科学中,算法的时间复杂度是衡量算法执行时间与输入规模之间关系的度量。
在本文中,我们将深入探讨KMP算法的时间复杂度。
KMP算法的时间复杂度可通过三个方面来分析:预处理阶段的时间复杂度、匹配阶段的时间复杂度以及总体时间复杂度。
1. 预处理阶段的时间复杂度在KMP算法中,要先对模式串进行预处理,生成部分匹配表(Partial Match Table),也称为最长公共前后缀表(Longest Proper Prefix which is also Sufix,简称为LPS表)。
这个过程的时间复杂度是O(m),其中m是模式串的长度。
在生成部分匹配表的过程中,KMP算法利用了前缀与后缀的性质,通过动态规划的方式计算每个位置的最长匹配长度。
虽然这个过程需要遍历整个模式串,但是每次计算的操作都具有重叠子问题的性质,因此可以通过状态转移方程高效地计算出来。
2. 匹配阶段的时间复杂度在匹配阶段,KMP算法将主串与模式串进行逐个字符的比较,并利用已经生成的部分匹配表来决定下一次比较的位置。
这个过程的时间复杂度是O(n),其中n是主串的长度。
在匹配过程中,KMP算法利用了部分匹配表的信息,根据当前位置的匹配长度来确定下一次比较的位置。
通过避免无效的比较,KMP 算法可以在最坏情况下实现线性的时间复杂度。
3. 总体时间复杂度KMP算法的总体时间复杂度是预处理阶段的时间复杂度与匹配阶段的时间复杂度之和。
即O(m) + O(n) = O(m + n)。
从总体时间复杂度可以看出,KMP算法的执行时间与主串和模式串的长度之和成正比。
相比于朴素的字符串匹配算法,KMP算法可以大大提高匹配的效率,尤其是在模式串较长的情况下。
总结:KMP算法的时间复杂度是O(m + n),其中m是模式串的长度,n是主串的长度。
通过对模式串进行预处理并利用部分匹配表的信息,KMP算法可以高效地在主串中查找所有匹配模式串的位置。
字符串匹配问题的算法步骤字符串匹配是计算机科学中常见的问题,主要用于确定一个字符串是否包含另一个字符串。
解决这个问题的算法可以分为暴力匹配算法、Knuth-Morris-Pratt(KMP)算法和Boyer-Moore(BM)算法等。
暴力匹配算法是最简单的一种方法。
它的基本思想是从主串的第一个字符开始,依次和模式串的每个字符进行比较,直到找到一个字符不匹配为止。
如果找到了不匹配的字符,则将主串的指针后移一位,重新开始匹配。
如果匹配成功,模式串的指针向后移一位,主串的指针也向后移一位,继续匹配。
这个过程一直进行下去,直到模式串的指针到达模式串的末尾,或者找到了一个匹配的子串。
尽管暴力匹配算法很简单,但是它的时间复杂度较高,为O(m*n),其中m是主串的长度,n是模式串的长度。
当主串和模式串很长时,暴力匹配算法的效率就会很低。
为了提高字符串匹配的效率,有很多其他的算法被提出。
其中比较著名的是KMP算法和BM算法。
KMP算法的核心思想是,当发生不匹配的情况时,不需要回溯主串的指针,而是通过已经匹配的部分字符的信息,将模式串的指针移动到一个新的位置,从而避免了不必要的比较。
具体来说,KMP算法在匹配的过程中,通过建立一个部分匹配表(Partial Match Table),来记录模式串中每个位置的最长前缀后缀的长度。
当发生不匹配的情况时,根据部分匹配表的信息,可以将模式串的指针直接移动到下一个可能匹配的位置。
BM算法是一种基于启发式的匹配算法,它的核心思想是从模式串的尾部开始匹配,并根据已经匹配的部分字符的信息,跳跃式地移动模式串的指针。
具体来说,BM算法分别构建了坏字符规则和好后缀规则。
坏字符规则用于处理主串中与模式串不匹配的字符,找到最右边的该字符在模式串中的位置,并移动模式串的指针到对齐该字符。
好后缀规则用于处理主串中与模式串匹配的部分,找到最右边的该部分在模式串中的位置,并移动模式串的指针到对齐该部分。
BF算法与KMP算法BF(Brute Force)算法是普通的模式匹配算法,BF算法的思想就是将⽬标串S的第⼀个字符与模式串T的第⼀个字符进⾏匹配,若相等,则继续⽐较S的第⼆个字符和 T的第⼆个字符;若不相等,则⽐较S的第⼆个字符和T的第⼀个字符,依次⽐较下去,直到得出最后的匹配结果。
BF算法实现:1int BF(char S[],char T[],int pos)2 {//c从第pos位开始搜索匹配3int i=pos,j=0;4while(S[i+j]!='\0'&&T[j]!='\0')5 {6if(S[i+j]==T[j])7 j++;8else9 {10 i++;11 j=0;12 }13 }14if(T[j]=='\0')15return i+1;16else17return -1;18 }BF算法⽐较直接,是⼀种蛮⼒算法,该算法最坏情况下要进⾏M*(N-M+1)次⽐较,为O(M*N),下⾯来看⼀个效率⾮常⾼的字符串匹配算KMP算法完成的任务是:给定两个字符串S和T,长度分别为n和m,判断f是否在S中出现,如果出现则返回出现的位置。
常规⽅法是遍历KMP算法思想:实例1优化的地⽅:如果我们知道模式中a和后⾯的是不相等的,那么第⼀次⽐较后,发现后⾯的的4个字符均对应相等,可见a下次匹配的位置实例2由于abc 与后⾯的abc相等,可以直接得到红⾊的部分。
⽽且根据前⼀次⽐较的结果,abc就不需要⽐较了,现在只需从f-a处开始⽐较即可。
说明主串对应位置i的回溯是不必要的。
要变化的是模式串中j的位置(j不⼀定是从1开始的,⽐如第⼆个例⼦)j的变化取决于模式串的前后缀的相似度,例2中abc和abc(靠近x的),前缀为abc,j=4开始执⾏。
下⾯我们来看看Next()数组:定义:(1)next[0]= -1 意义:任何串的第⼀个字符的模式值规定为-1。
kmp算法pmt的值PMT的值是KMP算法中的一个重要概念,它代表了模式串中每个位置上的最长相同前缀后缀的长度。
在KMP算法中,PMT的值被用来确定当遇到不匹配字符时,模式串应该向右移动的位置,以提高匹配的效率。
KMP算法是一种字符串匹配算法,用于在一个文本串中查找一个模式串的出现位置。
与暴力匹配算法相比,KMP算法具有更高的效率。
PMT的值的计算是KMP算法中的关键步骤之一,下面将详细介绍PMT 的计算方法。
我们需要了解最长相同前缀后缀的概念。
对于一个字符串,它的前缀是指从开头到某个位置的子串,后缀是指从某个位置到末尾的子串。
例如,字符串"abcabc"的前缀有"","a","ab","abc",后缀有"","c","bc","abc"。
最长相同前缀后缀即是指一个字符串既是它的前缀,又是它的后缀,并且长度最长。
在KMP算法中,我们通过计算模式串的PMT数组来得到每个位置上的最长相同前缀后缀的长度。
具体计算过程如下:1. 初始化PMT数组,将第一个位置的值设为0。
2. 从第二个位置开始,依次计算每个位置上的PMT值。
3. 假设当前位置为i,PMT[i-1]表示前一个位置上的最长相同前缀后缀的长度。
我们需要判断当前位置的字符是否与PMT[i-1]位置上的字符相等。
- 如果相等,那么当前位置上的最长相同前缀后缀的长度就是PMT[i-1]+1。
- 如果不相等,我们可以利用PMT数组来找到一个更短的相同前缀后缀,并继续判断是否相等。
4. 重复步骤3,直到计算完所有位置上的PMT值。
通过上述步骤,我们就可以得到模式串的PMT数组。
在KMP算法中,当遇到不匹配字符时,我们可以利用PMT数组来确定模式串向右移动的位置。
具体操作如下:假设当前文本串的位置为i,模式串的位置为j。
3)基金项目:重庆市自然科学基金项目(CSTC2007BB2178和CSTC2005BB2190)支持。
邓一贵 博士研究生,主要研究方向为计算机网络及信息安全。
计算机科学2008Vol 135№16 基于字符频率及分治法的字符串模式匹配算法3)邓一贵1,2(重庆大学计算机学院 重庆400044)1 (重庆大学信息与网络管理中心 重庆400044)2摘 要 本文提出的基于字符使用频率及分治法的改进字符串模式匹配算法可以在扫描被匹配目标串时每次跳过的字符在统计结果上比目前广泛使用的Boyer 2Moore 算法跳过的字符更多,进一步减少了匹配的统计次数。
关键词 字符串模式匹配,字符使用频率,分治 String Pattern Matching Algorithm B ased on Frequencies of Characters and Dividing and ConqueringDEN G Y i 2gui 1,2(College of Computer Science ,Chongqing University ,Chongqing 400044,China )1(Information and Network Center ,Chongqing University ,Chongqing 400044,China )2Abstract The skipped characters in the algorithm based on frequencies of characters and dividing and conquering are more in statistics than ones in Boyer 2Moore algorithm popularly used at present.The matching statistical times using algorithm presented in the paper are reduced.K eyw ords String pattern matching ,Frequencies of characters ,Divide and conquer 1 引言根据入侵特征是否已知来分,入侵检测可以分为已知特征的误用检测和未知的异常检测。
扩展kmp算法扩展KMP算法什么是扩展KMP?扩展kmp是求模式串和主串的每个后缀的最长公共前缀长度。
扩展KMP算法是利⽤前⾯的已知条件降低多余匹配,达到缩短时间的算法。
扩展KMP算法⽬的是得到next数组和extend数组。
next[ i ] 表⽰的是从⾃⼰的第i位開始。
模式串T与⾃⼰匹配的字符个数。
extend[ i ] 表⽰的是从主串S的第i位開始,模式串T与主串S匹配的字符个数。
扩展KMP算法的思路:先介绍⼏个⽐較重要的參数:a:当前求next值或者extend值时使得p最⼤时的位置。
p:当前⽐較过的最⼤位置。
p=a+next[ a ]-1或者p=a+extend [ a ]-1。
这个式⼦不难理解吧。
l:是利⽤模式串T的⾃相似性求出的当前第i位的的最长公共前缀长度,可是并不⼀定等于实际的最长公共前缀长度。
这仅仅是依据已经匹配过得数据得出的结论。
后没有匹配过得地⽅谁也说不定。
或许没匹配过得地⽅也同样呢。
也就是说extend[ i ]>=l。
或者next[ i ]>=l。
l=next[ i-a ]。
注意不管是求next 还是extend 都是同⼀个式⼦。
求next数组:next [ 0 ]等于字符串T的长度。
通过逐个⽐較的⽅法求出next [ 1 ]。
然后逐个求第2~n的next值。
推断l+i-1>=p是否成⽴。
即推断通过模式串⾃相似性求出的最长公共⼦串是否超过已经⽐較过的最⼤位置。
若成⽴,继续向后⽅没有⽐較过的位置⽐較。
若匹配⾃加1,直到不匹配为⽌此时的值即为next[ i ]的值。
若不成⽴,next [ i ]=l 。
求extend数组:通过逐个⽐較求出extend[ 0 ]。
然后逐个求第1~n的extend值。
推断l+i-1>=p是否成⽴。
即推断通过模式串⾃相似性求出的最长公共⼦串是否超过已经⽐較过的最⼤位置。
若成⽴。
继续向后⽅没有⽐較过的位置⽐較。
若匹配⾃加1,直到不匹配为⽌此时的值即为extend[ i ]的值。
字符串匹配方法引言:字符串匹配是计算机科学中一项重要的技术,它在文本处理、数据分析、搜索引擎等领域都有广泛的应用。
本文将介绍几种常见的字符串匹配方法,包括暴力匹配、KMP算法、Boyer-Moore算法和正则表达式。
一、暴力匹配算法暴力匹配算法,也称为朴素匹配算法,是最简单直观的字符串匹配方法。
它的思想是从待匹配文本的第一个字符开始,依次与模式串进行比较,若匹配失败则移动到下一个字符继续比较,直到找到匹配的子串或者遍历完整个文本。
该算法的时间复杂度为O(n*m),其中n为文本长度,m为模式串长度。
二、KMP算法KMP算法是一种高效的字符串匹配算法,它的核心思想是通过预处理模式串,构建一个部分匹配表(Next数组),以便在匹配过程中根据已匹配的前缀字符来确定下一次匹配的位置。
这样可以避免不必要的回溯,提高匹配效率。
KMP算法的时间复杂度为O(n+m),其中n为文本长度,m为模式串长度。
三、Boyer-Moore算法Boyer-Moore算法是一种基于比较字符的右移策略的字符串匹配算法。
它的主要思想是从模式串的末尾开始与待匹配文本比较,若匹配失败则根据预先计算好的字符移动表来决定模式串的右移位数。
这样可以根据比较结果快速确定下一次比较的位置,从而提高匹配效率。
Boyer-Moore算法的时间复杂度为O(n/m),其中n为文本长度,m为模式串长度。
四、正则表达式正则表达式是一种强大的字符串匹配工具,它通过一种特定的语法规则来描述字符串的模式,并通过匹配模式来判断字符串是否符合要求。
正则表达式可以实现复杂的匹配功能,包括字符匹配、重复匹配、分组匹配等。
在文本处理、数据清洗、搜索引擎等领域都有广泛的应用。
结论:字符串匹配是计算机科学中一项重要的技术,不同的匹配方法适用于不同的应用场景。
暴力匹配算法简单直观,适用于模式串较短的情况;KMP算法通过预处理模式串,提高匹配效率;Boyer-Moore算法通过右移策略,减少不必要的比较次数;正则表达式可以实现复杂的匹配功能。
kmp算法[编辑本段]kmp算法-概述一种改进的字符串匹配算法,由 D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。
[编辑本段]kmp算法-学习介绍完全掌握KMP算法思想学过数据结构的人,都对KMP算法印象颇深。
尤其是新手,更是难以理解其涵义,搞得一头雾水。
今天我们就来面对它,不将它彻底搞懂,誓不罢休。
如今,大伙基本上都用严蔚敏老师的书,那我就以此来讲解KMP 算法。
(小弟正在备战考研,为了节省时间,很多课本上的话我都在此省略了,以后一定补上。
)严老的《数据结构》79页讲了基本的匹配方法,这是基础。
先把这个搞懂了。
80页在讲KMP算法的开始先举了个例子,让我们对KMP的基本思想有了最初的认识。
目的在于指出“由此,在整个匹配的过程中,i指针没有回溯,”。
我们继续往下看:现在讨论一般情况。
假设主串:s: ‘s(1) s(2) s(3) ……s(n)’; 模式串:p: ‘p(1) p(2) p(3)…..p(m)’把课本上的这一段看完后,继续现在我们假设主串第i个字符与模式串的第j(j<=m)个字符‘失配’后,主串第i个字符与模式串的第k(k<j)个字符继续比较此时,s(i)≠p(j), 有主串:S(1)……s(i-j+1)……s(i-1) s(i) ………….|| (相配) || ≠(失配)匹配串:P(1) ……. p(j-1) p(j)由此,我们得到关系式‘p(1) p(2) p(3)…..p(j-1)’= ’s(i-j+1)……s(i-1)’由于s(i)≠p(j),接下来s(i)将与p(k)继续比较,则模式串中的前(k-1)个字符的子串必须满足下列关系式,并且不可能存在k’>k 满足下列关系式:(k<j),‘p(1) p(2) p(3)…..p(k-1)’= ’s(i-k+1)s(i-k+2)……s(i-1)’即:主串:S(1)……s(i-k +1) s(i-k +2) ……s(i-1) s(i) ………….|| (相配) || || ?(有待比较)匹配串:P(1) p(2) ……p(k-1) p(k)现在我们把前面总结的关系综合一下有:S(1)…s(i-j +1)…s(i-k +1) s(i-k +2) ……s(i-1) s(i) ……|| (相配) || || || ≠(失配)P(1) ……p(j-k+1) p(j-k+2) ….... p(j-1) p(j)|| (相配) || || ?(有待比较)P(1) p(2) ……. p(k-1) p(k)由上,我们得到关系:‘p(1) p(2) p(3)…..p(k-1)’= ’s(j-k+1)s(j-k+2)……s(j-1)’接下来看“反之,若模式串中存在满足式(4-4)。
《KMP字符串模式匹配算法》教学课例程玉胜安庆师范学院计算机与信息学院KMP字符串模式匹配是数据结构课程中一个重要的知识点,也是一个难点(学过KMP 算法的同学100%认为:KMP是数据结构课程中最难的部分)。
为了消除他们对KMP算法学习的恐惧心理,激发他们的学习兴趣,调动其积极性,显得尤为重要。
基于以上,我们根据学生的认知特点和接受水平,对教材内容进行了重新构建,并按照数据结构中“时间复杂度”概念,增加了不同模式匹配算法的运行时间,动态逼真的显示了算法的“时间”性能,获得了较好的教学效果。
一、教学目标知识目标:让学生了解KMP算法应用的普遍性。
如:在目前众多的文字处理软件中得到广泛应用,如Microsoft Word中的“查找”或“替换”操作。
而这种操作实现的机制,同学们特别是计算机专业的学生很少去想过。
能力目标:要求学生体验一个完整的抽象数据类型(ADT)的实现方法和过程,并学会判断、计算算法优劣的方法。
价值目标:消除恐怖的学习心态,让学生感悟数据结构算法实际应用价值,从而激发学习的兴趣,形成积极主动式学习的态度。
二、教材分析使用教材是清华大学严蔚敏教授并由清华大学出版社出版的《数据结构(C语言版)》,该教材难度较大,其实验方法特别是ADT方法在教材中介绍较少,而且KMP算法更是从理论分析的角度介绍了匹配算法和next的计算,自学难度很大;虽然该节知识点属于“**(表示难度较大,可以不讲)”,但是其又是考研的一个热点,所以我们又不得不讲。
三、教学重点、难点教学重点:KMP算法中的next和改进的nextval计算教学难点:KMP算法中如何计算next值四、教具准备卡片:多个字符串,字符串指针强力磁吸:6个五、互动式教学过程教学内容教师活动学生活动目标状态创设情境引入课题目前的众多软件中,“查找”、“替换”等操作实现方法,要求学生举例。
给出一篇word文档完成在上述文档中从当前位置向后查找“计算机”或者向前查找“计算机”字符串的方法。
这些软件中“查找”操作是怎么实现的?提出问题教师给出如下任务:手动演示如下两个字符串的查找操作。
例如:在串S=”abcabcabdabba”中查找T=”abcabd”的位置。
学生分组讨论,演示“查找”过程,如图(教具演示)我们发现比较到S[6] 和T[6]不等时,怎么办?解决问题| 简单匹配算法引入“简单匹配算法”给出上例的匹配过程前两步:第一趟、第二趟、学生完成匹配后面过程第三趟、第四趟、要求学生计算匹配次数:通过4次匹配,终于在S串中“查找”到T串,位置时4在第一趟比较后,进行的第二趟、第三趟比较有必要吗?进一步提出问题第一趟后,当S[6]≠T[6]时,◆第二趟进行S[2]与T[1]比较是必要的吗?◆第三趟进行S[3]与T[1]比较是必要的吗?◆第四趟进行S[4]与T[1]比较是必要的吗?◆第四趟进行S[4]与T[2]比较是必要的吗?学生讨论,然后找学生提问,最后证明。
如果是不必要的,那么第一趟后,当S[6]≠T[6]时,S[6]与T[ ]比较是必要的呢!“”怎么求?解决问题| KMP 匹配算法引入“MP匹配算法”第一趟,当S[6]≠T[6]时,S下标不是回溯到2,T下标也不是回溯到开始,而是根据T中T[6]==’d’的模式函数值(next[6]=3,为什么?后面讲)进行匹配,要求学生完成匹配过程当S[6]≠T[6]时,根据next[6]=3匹配过程:要求学生计算匹配次数:仅通过2次匹配,终于在S串中“查找”到T串,位置时4next[6]=3含义:其实这个3表示T[6]==’d’的前面有2个字符和开始的两个字符相同”怎么求串的模式值next[n]?教学重点内容| next 值的计算引入“模式值next[n]的计算”定义:略例二、求T=“abcab”的模式函数的值。
下标 1 2 3 4 5T a b c a bnext 0 1 1 1 2设T=“abcab”,S=“abcadcabcab”,利用KMP算法进行匹配,几次匹配成功?存在什么问题?问题的进一步提出第一趟:当出现S[5]≠T[5]时,根据next[5]=2,得:第二趟、第三趟、学生完成后面的工作:要求学生计算匹配次数:仅通过5次匹配,在S串中“查找”到T串,位置时7比如:“abcab”模式串中,NEXT值为(0 1 1 1 2 )。
当比较到T[5]=b不成功时,原NEXT的值跟T[2]比较,可事实上,T[2]也是b,与T[5]相同,所以可以直接跟T[1]比较。
可见,第二趟比较是多余的,那么如何改进呢?教学重点内容|next[n]改进为nextval[n]:如果T[j]≠T[k],k=next[j] 否则k=next[k]要求学生计算nextval值下标 1 2 3 4 5T a b c a cnext 0 1 1 1 2完成理论教学目标,那么在计算机中我们怎样编程实现?另外几种算法的时间复杂度怎样计算?nextval 值的计算nextval 0 ? ? ? ? 根据nextval,计算改进后的匹配次数。
成品介绍| ADT 简单匹配算法演示:简单匹配算法介绍抽象数据类型的简单匹配算法实现及其时间复杂度计算方法。
进一步认识“数据封装”的含义,在原有程序基础上增加“匹配次数”的计算方法:结果:怎样实现KMP算法及其改进的模式匹配算法主动式学习与模仿| KMP 算法实现教师辅导学生模仿“简单匹配算法”实现代码,实现“KMP算法”程序调试过程时,学生可以向下面的学生求助,也可以向老师求助进一步熟悉了ADT编程方法和调试机巧课堂作业1. 给出字符串‘abacabaaad’在KMP算法中的next和nextval数组。
2.对S=’aabcbabcaabcaaba’,T=’bca’,画出T为模式串,S为目标串的匹配过程。
10分钟完成,并检查掌握情况课后作业:1.求串’ababaaababaa’的next函数值。
2模式串t=’abcaabbcaabdab’,求模式串的next和nextval函数的值。
提高创新仿照WORD文档中的“查找”操作,编程实现在文本文件中查找指定的字符串位置。
学生讨论,查找相关文献资料将结果上传至作业存储的ftp服务器ftp://219.231.49.249网上答疑课堂作业、课后作业答案将在数据结构在线学习网站—网站公告”中公布在学习过程中遇到的不懂的、或者难题,请同学继续在“数据结构在线学习网站—网上答疑”中提交对于“网上答疑”中的问题,我们将及时回复,目前“网上答疑”的开通,极大的方便了老师与学生的交流,反映效果较好。
附:详细的教学过程1、创设情境,引入课题老师:目前的众多软件中,“查找”、“替换”等操作实现方法,要求学生举例。
给出一篇word文档学生:完成在上述文档中从当前位置向后查找“计算机”或者向前查找“计算机”字符串的方法。
2、提出问题,解决问题老师:这些软件中“查找”操作是怎么实现的?教师给出如下任务:手动演示如下两个字符串的查找操作,例如:在串S=”abcabcabdabba”中查找T=”abcabd”的位置。
学生分组讨论,演示“查找”过程,如图1(教具演示)老师提出问题:我们发现比较到S[6] 和T[6]不等时,怎么办?解决问题:引入“简单匹配算法”3、简单匹配算法基本的模式匹配算法:以主串的某个字符与子串的第一个字符相比较,若相等,则继续比较二者的后一个字符,否则主串的字符指针从开始与子串第一个字符比较处后移一个位置,而子串的字符指针重新指向子串的第一个字符。
当这样一个失配发生时,T下标必须回溯到开始,S下标回溯的长度与T相同,然后S 下标增1,然后再次比较。
如图:这次立刻发生了失配,T下标又回溯到开始,S下标增1,然后再次比较。
如图:又一次发生了失配,所以T下标又回溯到开始,S下标增1,然后再次比较。
这次T中的所有字符都和S中相应的字符匹配了。
函数返回T在S中的起始下标4。
如图:上述通过4次匹配,终于在S串中“查找”到T串,位置时4。
老师再次提出问题:在第一趟比较后,进行的第二趟、第三趟比较有必要吗?提问的形式:让学生讨论如下问题,第一趟后,当S[6]≠T[6]时,第二趟进行S[2]与T[1]比较是必要的吗?第三趟进行S[3]与T[1]比较是必要的吗?第四趟进行S[4]与T[1]比较是必要的吗?第四趟进行S[4]与T[2]比较是必要的吗?如果是不必要的,那么第一趟后,当S[6]≠T[6]时,S[6]与T[ ?]比较是必要的呢!解决问题:引入“KMP匹配算法”4、KMP 匹配算法KMP算法:KMP算法是对传统模式匹配算法的较大改进,在传统的模式匹配算法中,当出现主串中的字符与子串中的字符不等时,同时向前回溯了两个指针,一个是主串的指针,一个是子串的指针。
而KMP算法的基本思路是在不回溯主串的指针,而只回溯子串的指针的情况下完成模式匹配,这样就省去了回溯主串指针进行比较的一部分时间。
KMP算法的核心思想是利用已经得到的部分匹配信息来进行后面的匹配过程。
还是相同的例子,在S=”abcabcabdabba”中查找T=”abcabd”,如果使用KMP匹配算法,当第一次搜索到S[6] 和T[6]不等后,S下标不是回溯到2,T下标也不是回溯到开始,而是根据T中T[6]==’d’的模式函数值(next[6]=3,为什么?后面讲),直接比较S[6] 和T[3]是否相等,因为相等,S和T的下标同时增加;因为又相等,S和T的下标又同时增加。
最终在S中找到了T。
如图:next[6]=3含义:其实这个3表示T[6]==’d’的前面有2个字符和开始的两个字符相同”。
请看图:因为,S[5] ==T[5],S[4] ==T[4],根据next[6]=3,有T[4]==T[1],T[5] ==T[2],所以S[4]==T[1],S[5] ==T[2](两对相当于间接比较过了),因此,接下来比较S[6] 和T[3]是否相等。
有人可能会问:S[4]和T[1],S[5] 和T[2]是根据next[6]=3间接比较相等,那S[2]和T[1],S[3] 和T[1]之间又是怎么跳过,可以不比较呢?因为S[1]=T[1],S[2]=T[2],S[3]=T[3],而T[1] != T[2], T[2] != T[3],==> S[1] != S[2],S[2] != S[3],所以S[2] != T[1],S[3] != T[1]. 还是从理论上间接比较了。
5 . 怎么求串的模式值next[n]定义:0 如果j=1next[j]={ Max{k|1<k<j且'p1...p k-1'='p j-k+1...p j-1'1 其它情况(1)next[1]=0 意义:任何串的第一个字符的模式值规定为0。