KMP实验报告
- 格式:doc
- 大小:36.00 KB
- 文档页数:4
数据结构课程设计使用kmp算法实现字符串的模式匹配问题本次数据结构课程设计将使用KMP算法实现字符串的模式匹配问题。
KMP算法,全称是Knuth-Morris-Pratt算法,它是一种字符串匹配算法,可以用来解决"在一个文本串S内查找一个模式串P的出现位置"这样的问题。
在字符串匹配问题中,最简单朴素的算法就是暴力匹配,它的时间复杂度是O(m*n),其中m为模式串的长度,n为文本串的长度。
而KMP算法通过预处理模式串,使得可以在O(n)的时间内查找出文本串中的所有模式串出现的位置。
具体来说,KMP算法的核心思想是:当匹配失败时,尽可能地跳过已经匹配的部分,从而实现快速匹配。
而跳过已经匹配的部分的方法则是通过对模式串进行预处理,得到一个next数组,next数组中存放的是当当前字符匹配失败后,应该跳过已匹配的字符数量,从而能够加速匹配。
下面是使用KMP算法实现字符串模式匹配的主要步骤:1.预处理模式串,得到next数组2.在文本串S中,按照模式串P进行匹配,记录匹配成功的位置3.如果匹配成功,则将模式串和文本串移到下一个位置继续匹配4.如果匹配失败,则根据next数组跳过已匹配的字符数量,从而加速匹配本次课程设计的具体任务包括:1.了解KMP算法的基本原理和实现方法2.使用C++语言实现KMP算法,可以参考以下代码:```c++#include <iostream>#include <cstring>#include <cstdio>using namespace std;const int N = 1e6 + 10;char p[N], s[N];int ne[N];int main(){cin >> s + 1 >> p + 1;int n = strlen(s + 1), m = strlen(p + 1);//预处理next数组for(int i = 2, j = 0; i <= m; i++){while(j && p[i] != p[j + 1]) j = ne[j];if(p[i] == p[j + 1]) j++;ne[i] = j;}//匹配过程for(int i = 1, j = 0; i <= n; i++){while(j && s[i] != p[j+1]) j = ne[j];if(s[i] == p[j+1]) j++;if(j == m){printf("%d ", i - m);j = ne[j];}}return 0;}```3.使用自己设计的测试数据对代码进行测试,并对运行结果进行分析和总结。
模式匹配中的KMP算法的实现KMP算法(Knuth-Morris-Pratt算法)是一种用于字符串匹配的快速算法,通过有效利用已匹配部分的信息来跳过一些不必要的比较,从而提高匹配效率。
KMP算法是由Donald Knuth、Vaughan Pratt和JamesH.Morris于1977年提出的。
KMP算法的核心思想是利用"部分匹配表"来确定当模式串与主串不匹配时,模式串应该向后滑动的位置。
部分匹配表是模式串的前缀子串中的最长的可匹配的真前缀和后缀的长度。
下面是KMP算法的实现过程:1.首先,根据模式串生成部分匹配表。
部分匹配表中第i个位置的值表示模式串的前i个字符组成的子串的最长可匹配的真前缀和后缀的长度。
2.利用部分匹配表进行匹配。
在匹配过程中,用两个指针i和j分别表示主串和模式串的位置。
如果当前字符匹配成功,则i和j都向后移动一位;如果当前字符不匹配,则根据部分匹配表确定模式串应该向后滑动的位置。
下面是KMP算法的Python实现:```pythondef generate_next(pattern):next = [0] * len(pattern)next[0] = -1i,j=0,-1while i < len(pattern) - 1:if j == -1 or pattern[i] == pattern[j]: i+=1j+=1next[i] = jelse:j = next[j]return nextdef kmp_search(text, pattern):next = generate_next(pattern)i,j=0,0while i < len(text) and j < len(pattern): if j == -1 or text[i] == pattern[j]:i+=1j+=1else:j = next[j]if j == len(pattern):return i - jelse:return -1```在上述代码中,`generate_next`函数用于生成部分匹配表,`kmp_search`函数用于进行匹配。
KMP算法实现及优化方法KMP算法(Knuth-Morris-Pratt算法)是一种字符串匹配算法,用于在一个主文本字符串S内查找一个模式字符串P的出现位置。
KMP算法利用模式字符串中前缀和后缀的信息来跳过不必要的比较,从而提高查找的效率。
KMP算法的基本思想是,当出现不匹配时,通过已经部分匹配的信息,可以确定一部分字符是匹配的,可以直接跳过这部分已经匹配的字符,继续进行比较。
这个部分匹配的信息,就是模式字符串P自身的前缀和后缀的最长共有元素的长度,也称为前缀函数或部分匹配表。
1.构建部分匹配表:对模式字符串P进行分析,计算出每个位置的最长共有元素的长度,存储在一个部分匹配表中。
2.在主文本字符串S中进行匹配:从主文本字符串的第一个位置开始,逐个字符与模式字符串进行比较,如果字符相等则继续比较下一个字符,如果字符不相等,则根据部分匹配表跳过一部分字符,继续比较,直到找到匹配的位置或者比较结束。
优化KMP算法可以从两方面进行:1.改进部分匹配表的构建:KMP算法中最耗时的部分是部分匹配表的构建,可以对其进行优化。
一种优化方法是使用动态规划思想,利用已计算的部分匹配值来计算新的部分匹配值,从而减少计算量。
2.改进模式字符串的跳过方式:KMP算法中,当在主文本字符串S中比较到一些位置时,如果字符不匹配,则根据部分匹配表来跳过一部分字符。
可以根据具体问题的特点,利用更加有效的跳过方式来提高算法的效率。
一种常见的跳过方式是使用好后缀和坏字符的信息,来决定向右移动的步数。
总结起来,KMP算法是一种高效的字符串匹配算法,通过部分匹配表的构建和优化,可以在O(n+m)的复杂度内完成匹配。
在实际应用中,根据具体问题的特点,可以进一步改进KMP算法来提高效率。
KMP算法研究与实现作者:解晨王瑜来源:《电脑知识与技术》2013年第20期摘要:文字是传播信息的关键载体之一,是表达人类情感的重要方式,更是传承文化的最关键最基本的手段。
理所当然,文本编辑程序是计算机中最重要的应用之一。
自从计算机被发明以来,字符,字符串,文本,就一直于人类打着交道。
在文本编辑程序中,经常会出现要搜索一段特定文字以及对其位置定位的情况,当文本内容庞大,或者要搜索的内容出现相当频繁时,良好的搜索算法对效率的提高就相当可观了。
该文研究了效率极高的KMP字符串匹配算法,并使用C语言对算法进行了实现。
关键词:查找搜索;字符串匹配;KMP算法中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2013)20-4696-03文本,一直是计算机这一领域中最基本的元素,无论是计算机刚诞生的年代,还是如今多媒体技术绚烂夺目的时代,文本一直都作为奠基性质的元老角色而存在着。
在对文本的编辑中,会遇到需要查找匹配特定模式的情况。
比如,在一个文本文件中查找“ABC”这一小段,或者查找“不知道”这一词语。
当文本的内容比较少时,人们可以通过简单的逐行查找来找到匹配的特定模式,然而,当文本具备一定的规模后,在其中查找特定的模式就足以令人抓狂了。
在当下这个信息大爆炸的时代,拥有大规模内容的文本实在不在少数,无论是金融界、文学界、政界还是计算机专业界,每天面对大量的文字信息实在令人欲罢不能,在其中寻找重要的关键词、关键句或者关键段落时,更是令人痛不欲生,即使是交给计算机去做,也需耗费大量的开销。
因此,设计出一种好的算法,以高效地查找大容量文本文件中的特定匹配模式,不仅可以大大提高文本编辑的响应性能,还能改善人类的生活。
此外,随着学科之间交叉性的提高,很多领域也需要在大量的信息中查找某些特定模式及其出现的位置,例如DNA测序定位、海洋数据查询、高效搜索引擎等。
幸运的是,目前已经有了高效的字符串匹配算法,并且,此类算法仍在不断发展进化,向着更高的效率进发。
基于kmp算法的dna匹配实现全过程课程设计DNA匹配是一项重要的遗传学研究技术,可以用于识别和匹配DNA 序列。
KMP算法是一种字符串匹配算法,其核心思想是通过利用待匹配字符串本身的信息来实现快速匹配。
本课程设计旨在通过基于KMP算法的DNA匹配实现全过程来帮助学生加深对KMP算法和DNA匹配的理解,并且提供关于实现和优化该算法的实践。
以下是本课程设计的详细内容。
一、课程设计目标:1.了解DNA序列和DNA匹配的基本概念和原理;2.学习KMP算法的原理和实现方法;3.熟悉KMP算法在DNA匹配中的应用;4.掌握基于KMP算法的DNA匹配实现全过程。
二、课程设计内容:1. DNA序列和DNA匹配的基本概念和原理(理论课):- DNA序列的组成和结构;- DNA匹配的意义和应用;-常见的DNA序列匹配算法及其优缺点。
2. KMP算法的原理和实现方法(理论课):- KMP算法的基本原理和思想;- KMP算法的实现步骤;- KMP算法的时间复杂度分析;- KMP算法的优化方法。
3. KMP算法在DNA匹配中的应用(理论课):-如何利用KMP算法进行DNA序列匹配;- KMP算法在DNA序列匹配中的优势和局限性;-实际应用案例分析。
4.基于KMP算法的DNA匹配实现全过程(实践课):4.1实验环境的搭建和准备工作:-安装和配置必要的编程环境(例如Python、Java等);-导入和准备实验所需的DNA序列数据集。
4.2 KMP算法的实现:-掌握KMP算法的基本实现步骤;-根据实验要求,实现一个能够进行DNA序列匹配的KMP算法。
4.3实验结果的分析与总结:-运行实验代码,对DNA序列进行匹配;-分析实验结果,对算法的正确性和性能进行评估;-总结实验经验,并提出优化思路。
三、课程设计要求:1.学生需要具备一定的编程基础,能够理解和实现KMP算法。
2.学生需要熟悉DNA序列和DNA匹配的基本概念。
3.学生需要通过实验设计和实验结果的分析,加深对KMP算法和DNA匹配的理解。
一、实验目的1. 理解串的定义、性质和操作;2. 掌握串的基本操作,如串的创建、复制、连接、求子串、求逆序、求长度等;3. 熟练运用串的常用算法,如串的模式匹配算法(如KMP算法);4. 培养编程能力和算法设计能力。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019三、实验内容1. 串的创建与初始化2. 串的复制3. 串的连接4. 串的求子串5. 串的求逆序6. 串的求长度7. 串的模式匹配算法(KMP算法)四、实验步骤1. 串的创建与初始化(1)创建一个串对象;(2)初始化串的长度;(3)初始化串的内容。
2. 串的复制(1)创建一个目标串对象;(2)使用复制构造函数将源串复制到目标串。
3. 串的连接(1)创建一个目标串对象;(2)使用连接函数将源串连接到目标串。
4. 串的求子串(1)创建一个目标串对象;(2)使用求子串函数从源串中提取子串。
5. 串的求逆序(1)创建一个目标串对象;(2)使用逆序函数将源串逆序。
6. 串的求长度(1)获取源串的长度。
7. 串的模式匹配算法(KMP算法)(1)创建一个模式串对象;(2)使用KMP算法在源串中查找模式串。
五、实验结果与分析1. 串的创建与初始化实验结果:成功创建了一个串对象,并初始化了其长度和内容。
2. 串的复制实验结果:成功将源串复制到目标串。
3. 串的连接实验结果:成功将源串连接到目标串。
4. 串的求子串实验结果:成功从源串中提取了子串。
5. 串的求逆序实验结果:成功将源串逆序。
6. 串的求长度实验结果:成功获取了源串的长度。
7. 串的模式匹配算法(KMP算法)实验结果:成功在源串中找到了模式串。
六、实验总结通过本次实验,我对串的定义、性质和操作有了更深入的了解,掌握了串的基本操作和常用算法。
在实验过程中,我遇到了一些问题,如KMP算法的编写和调试,但在老师和同学的指导下,我成功地解决了这些问题。
数据结构课程设计设计说明书模式匹配中的KMP算法的实现学生姓名学号班级成绩指导教师数据结构课程设计评阅书课程设计任务书2011 —2012 学年第二学期专业:学号:姓名:课程设计名称:数据结构设计题目:模式匹配中的KMP算法的实现完成期限:自2012 年 2 月20 日至2012 年3 月 2 日共 2 周设计依据、要求及主要内容(可另加附页):指导教师(签字):教研室主任(签字):批准日期:年月日摘要设计了一个模式匹配中的KMP算法的软件,该软件具有创建字符串、显示字符串以及子串定位的操作。
本软件采用VC++作为软件开发环境,采用C语言各种语句和结构实现模式匹配中的KMP算法的一系列操作,并采用友好界面向用户提示所操作过程和所输入数据方式,操作简单,界面清晰,易于为用户所接受。
关键字:主串;子串;模式匹配目录1 课题描述 (6)2 需求分析 (7)3 概要设计 (8)4 详细设计 (12)5 程序编码 (15)6结果分析 (19)7 总结 (24)参考文献 (25)1 课题描述本次实验重在设计模式匹配中的KMP算法的实现,通过c语言作为编程语言,实现模式匹配中的KMP算法,其中包括创建字符串、显示字符串以及子串定位。
先输入一个主串S(长度为m),然后再输入一个模式串T(长度为n),并且m>=n,求出T在S中模式匹配的第一个位置,并显示出计算过程中的关键参量及计算结果。
旨在使用户在使用过程中能学会直接调用各种所需函数,以及掌握对模式匹配中的KMP算法的各种操作。
开发工具:c语言运行环境。
2 需求分析在字符串的匹配过程中,从模式串和主串的第一个字符开始比较,如果匹配的话就比较他们的第二位,第三位……以此类推。
如果比较的过程中主串S的第i位和模式串T的第j位不匹配,说明匹配不成功,则将模式串T向后移动,在这个时候,由于前i-1和j-1是匹配的,所以可以导出如果此时T中的前k个字符T1,和Tj以前的k个字符Tj-1,Tj-2...Tj-k+1相同,这时就直接把模式串T向前移动j-k位,这时T的当前比较位j 就变成了next[j]了,循环执行(KMP算法)。
KMP算法的Java实现例子以及测试分析背景简介:KMP算法用来处理字符串匹配的。
给你A,B两个字符串,检查B串是否是A串的子串,类似于Java的String.indexOf("")。
之所以叫做KMP,是因为这个算法是由Knuth、Morris、Pratt三个提出来的,取了这三个人的名字的头一个字母。
原理介绍:找到匹配失败时的最合适的回退位置,而不是简单的回退到子串的第一个字符(常规的枚举查找方式,是简单的回退到子串的第一个字符,接下来准备写一篇KMP算法的性能分析Java实现实例),即可提高查找的效率。
因此为了找到这个合适的位置,先对子串预处理,从而得到一个回退位置的数组。
过多的理论就不介绍了。
总体而言比较简单,KMP算一个经典的算法例子,很多笔试、面试也会问起。
现总结一下,放在这里供大家参考、交流,希望对大家有所帮助,下面直接给出实现例子,测试与分析也包含其中。
一、一个文件源代码KMP.java源代码为:package algorithm.kmp;/*** KMP算法的Java实现例子与测试、分析* @author 崔卫兵* @date 2009-3-25*/public class KMP {/*** 对子串加以预处理,从而找到匹配失败时子串回退的位置* 找到匹配失败时的最合适的回退位置,而不是回退到子串的第一个字符,即可提高查找的效率* 因此为了找到这个合适的位置,先对子串预处理,从而得到一个回退位置的数组* @param B,待查找子串的char数组* @return*/public static int[] preProcess(char [] B) {int size = B.length;int[] P = new int[size];P[0]=0;int j=0;//每循环一次,就会找到一个回退位置for(int i=1;i<size;i++){//当找到第一个匹配的字符时,即j>0时才会执行这个循环//或者说p2中的j++会在p1之前执行(限于第一次执行的条件下)//p1while(j>0 && B[j]!=B[i]){j=P[j];}//p2,由此可以看出,只有当子串中含有重复字符时,回退的位置才会被优化if(B[j]==B[i]){j++;}//找到一个回退位置j,把其放入P[i]中P[i]=j;}return P;}/*** KMP实现* @param parStr* @param subStr* @return*/public static void kmp(String parStr, String subStr) {int subSize = subStr.length();int parSize = parStr.length();char[] B = subStr.toCharArray();char[] A = parStr.toCharArray();int[] P = preProcess(B);int j=0;int k =0;for(int i=0;i<parSize;i++){//当找到第一个匹配的字符时,即j>0时才会执行这个循环//或者说p2中的j++会在p1之前执行(限于第一次执行的条件下)//p1while(j>0 && B[j]!=A[i]){//找到合适的回退位置j=P[j-1];}//p2 找到一个匹配的字符if(B[j]==A[i]){j++;}//输出匹配结果,并且让比较继续下去if(j==subSize){j=P[j-1];k++;System.out.printf("Find subString '%s' at %dn",subStr,i-subSize+1);}}System.out.printf("Totally found %d times for '%s'.nn",k,subStr);}public static void main(String[] args) {//回退位置数组为P[0, 0, 0, 0, 0, 0]kmp("abcdeg, abcdeh, abcdef!这个会匹配1次","abcdef");//回退位置数组为P[0, 0, 1, 2, 3, 4]kmp("Test ititi ititit! Test ititit!这个会匹配2次","ititit");//回退位置数组为P[0, 0, 0]kmp("测试汉字的匹配,崔卫兵。
北京理工大学珠海学院课程设计说明书2010 —2011 学年第二学期题目: 文学研究助手与模式匹配算法KMP学院:计算机科学与技术学院专业班级:学号:学生姓名:指导教师:成绩:时间:北京理工大学珠海学院课程设计任务书2010 ~2011学年第二学期学生姓名:专业班级:指导教师:工作部门:一、课程设计题目文学研究助手与模式匹配算法KMP二、课程设计内容(含技术指标)【问题描述】文学研究人员需要统计某篇英文小说中某些形容词的出现次数和位置。
试写一个实现这一目标的文字统计系统【任务要求】英文小说存于一个文本文件中。
待统计的词汇集合要一次输入完毕,即统计工作必须在程序的一次运行之后就全部完成。
程序的输出结果是每个词的出现次数和出现位置所在的行的行号,格式自行设计。
待统计的“单词”在文本串中不跨行出现,它或者从行首开始,或者前置以一个空格符。
模式匹配要基于KMP算法。
推广到更一般的模式集匹配问题,并设待查模式串可以跨行(提示:定义操作GetAChar)。
【测试数据】文本文件为testword.c待统计的词集:if、else、for、while、return、void、int、char、typedef、struct三、进度安排1.初步设计:写出初步设计思路,进行修改完善,并进行初步设计。
2.详细设计:根据确定的设计思想,进一步完善初步设计内容,按要求编写出数据结构类型定义、各算法程序、主函数。
编译分析调试错误。
3.测试分析:设计几组数据进行测试分析,查找存在的设计缺陷,完善程序。
4.报告撰写:根据上面设计过程和结果,按照要求写出设计报告。
5.答辩考核验收:教师按组(人)检查验收,并提出相关问题,以便检验设计完成情况。
四、基本要求1.在设计时,要严格按照题意要求独立进行设计,不能随意更改。
若确因条件所限,必须要改变课题要求时,应在征得指导教师同意的前提下进行。
2.在设计完成后,应当场运行和答辩,由指导教师验收,只有在验收合格后才能算设计部分的结束。
实验报告
题目:编制字符串匹配的KMP算法
班级:理科实验四班 姓名:木三
学号:****** 完成日期:2016.4.17
一、需求分析
1.字符串匹配试求子串位置的定位函数,普通的字符串匹配函数时间复杂度较大
达到了O(m*n),而KMP算法则可以将时间复杂度简化到O(m+n)。
2.本演示程序中,字符串的元素为除换行、退格等字符外的其他字符,字符串长
度<=MAXSIZE,字符串的输入的形式为string[0]储存长度,从string[1]开始存
储字符,并以’\0’做结束标志,字符串中字符顺序不限,且允许出现重复字符,
不能出现非法字符。输入两个字符串后,输入一个整形数pos,pos<=MAXSIZE,
pos的值必须合法。输出的结果为一个整形数,表示,从第一个字符串的pos位
置开始,之后的子串能否与第二个字符串匹配,若能,输出匹配首地址的编号,
若不能,输出0。
3.程序执行的命令包括:
1)构造字符串1;
2)构造字符串2;
3)kmp算法;
4)得到next[];
4.测试数据
1)string1=’abababab’ string2=’aba’ pos=1 output=1;
2)string1=’abababab’ string2=’aba’ pos=6 output=0;
二、概要设计
KMP算法是D.E.Knuth与V.R.Pratt和J.H.Morris同时发现的一种模式匹配的
高效算法,,可以在O(m+n)的时间数量级上完成串的模式匹配操作。其改进
在于:每当一趟匹配过程中出现的字符比较不等时,不需要回溯i指针,而是利
用已经得到的‚部分匹配‛的结果将模式向右‚滑动‛尽可能远的一段距离后,
继续进行比较。
为实现上述上述程序功能,应以串的定长顺序存储表示来存放字符串,且需要串
的抽象数据类型。
1.串的定长顺序存储表示为:
#define MAXSTRLEN 255//用户可在255以内定义最大串长
typedef char SString[MAXSTRLEN+1];//0号单元存放串的长度
2.串的抽象数据类型定义为:
ADT String{
数据对象:D={ai|ai∈CharacterSet,i=1,2,...,n,n>=0}
数据关系:R1={
基本操作:
GetString(SString &S)
初始条件:存在串的指针。
操作结果:生成一个由键盘键入的字符串S。
strlen(SString S)
初始条件:串S存在。
操作结果:返回S的元素个数,称为串的长度。
Index(SString S,SString T,int pos)
初始条件:串S和T存在,T是非空串,1<=pos<=Strlength(S)-pos+1.
操作结果:若主串S中存在和串T值相同的子串,贼返回它在主串S中第pos
个字符之 后第一次出现的位置;否则函数值为0。
}//ADT String
3.KMP算法中,用到next函数,定义:
void get_next(SString T,int next[])
4.函数的调用关系图
main()->GetString()->strlenth()
->index_KMP->get_next()
三、调试分析
1.在GetString()中开始用了gets(S),S[0]没有用来记录字符串的长度,导致
在后续的程序中运算出错。
2.next函数在某些情况下存在缺陷。例如模式‘aaaaa’在和主串‘aaabaaaab’
匹配时,当i=4、j=4,时不匹配,需要进行多余的三次比较,实际上,因为模
式中第1、2、3、个字符和第4个字符都相等,因此不再需要和主串中第四个字
符进行比较,而可以将模式一气向右滑动4个字符的位置直接进行i=5、j=1时
的字符比较。这就是说,若按上述定义得到next[j]=k,而模式中pj=pk,则当
主串中字符si和pj不比较不等时,不需要在和pk进行比较,而直接和pnext[k]
进行比较,即此时的next[j]应该和next[k]相同。由此得到修正算法:
void get_nextval(SString T,int nextval[])
四、测试结果
1.S=’abababab’ T=’aba’ pos=1 :1;
2.S=’abababab’ T=’aba’ pos=6 :0;
五、附录
源程序文件清单:
#define MAXSTRLEN 255
#include
#include
#include
int next[MAXSTRLEN+1],nextval[MAXSTRLEN+1];
typedef char SString[MAXSTRLEN+1];
int Index_KMP(SString S,SString T,int pos)
{
int i,j=1;
i=pos;
while(i<=S[0]&&j<=T[0])
{
if(j==0||S[i]==T[j]){i++;j++;}
else j=next[j];
}
if(j>T[0])return i-T[0];
else return 0;
}
void get_next(SString T,int next[])
{
int i=1,j;
next[1]=0;
j=0;
while(i
if(j==0||T[i]==T[j])
{
++i;++j;
next[i]=j;
}
else j=next[j];
}
}
void get_nextval(SString T,int nextval[])
{
int i=1,j=0;
nextval[1]=0;
while(i
if(j==0||T[i]==T[j])
{
i++;j++;
if(T[i]!=T[j])nextval[i]=j;
else nextval[i]=nextval[j];
}
else j=nextval[j];
}
}
void GetString(SString &S)
{
gets(S+1);
S[0]=strlen(S+1);
}
int main()
{
SString S,T;
int pos;
GetString(S);
GetString(T);
get_next(T,next);
scanf("%d",&pos);
printf("%d",Index_KMP(S,T,pos));
return 0;
}