KR字符串匹配算法的研究与实现
- 格式:pdf
- 大小:146.06 KB
- 文档页数:3
数据结构课程设计使用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.使用自己设计的测试数据对代码进行测试,并对运行结果进行分析和总结。
文章作者:Slyar 文章来源:Slyar Home ( ) 转载请注明,谢谢合作。
KMP 算法是一种改进的字符串匹配算法,由D.E.Knuth 与V.R.Pratt 和J.H.Morris 同时发现,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP 算法)。
这周的数据结构课讲的是串,本以为老师会讲解KMP 算法的,谁知到他直接略过了...没办法只能自己研究,这一琢磨就是3天,期间我都有点怀疑自己的智商...不过还好昨天半夜终于想明白了个中缘由,总结一些我认为有助于理解的关键点好了...书上有的东西我就不说了,那些东西网上一搜一大片,我主要说一下我理解的由前缀函数生成的next 数组的含义,先贴出求next 数组的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void GetNext (char * t , int * next ){int i , j , len ;i = 0;j = -1;next [0] = -1;while (t [i ] != '\0'){if (j == -1 || t [i ] == t [j ]){i ++;j ++;next [i ] = j ;}else{j = next [j ];}}}当一个字符串以0为起始下标时,next[i]可以描述为"不为自身的最大首尾重复子串长度"。
也就是说,从模式串T[0...i-1]的第一个字符开始截取一段长度为m(m < i-1)子串,再截取模式串T[0...i-1]的最后m 个字符作为子串,如果这两个子串相等,则该串就是一个首尾重复子串。
我们的目的就是要找出这个最大的m 值。
例如:若 i = 4 ,则 i - 1 = 3 , m = next[4] = 2从T[0...3]截取长度为2的子串,为"ab"从T[0..3]截取最后2个字符,为"ab"此时2个子串相等,则说明 next[4] = 2 成立,也可证明 m = 2 为最大的m 值。
KMP算法数据结构中的字符串匹配算法KMP算法是一种高效的字符串匹配算法,它在数据结构中被广泛应用于解决字符串匹配问题。
KMP算法的核心思想是利用已经匹配过的信息,尽可能减少回溯的次数,从而提高匹配的效率。
本文将介绍KMP算法的原理、实现步骤以及应用场景,帮助读者更好地理解和运用这一经典的算法。
### 1. KMP算法原理KMP算法的原理基于两个重要概念:最长公共前缀和部分匹配值。
最长公共前缀是指一个字符串的前缀(不包括整个字符串本身)与该字符串的另一个后缀相同的最大长度;部分匹配值是指字符串的前缀与后缀的最长公共部分的长度。
KMP算法通过预处理模式串,构建部分匹配表,实现在匹配过程中的高效跳转,从而减少不必要的比较次数。
### 2. KMP算法实现步骤KMP算法的实现步骤主要包括以下几个关键步骤:#### 2.1 构建部分匹配表首先,需要对模式串进行预处理,计算出每个位置的部分匹配值。
这一步是KMP算法的关键,也是提高匹配效率的核心。
通过部分匹配表,可以在匹配过程中实现快速跳转,避免不必要的回溯。
#### 2.2 匹配过程在匹配过程中,利用部分匹配表中的信息,实现模式串相对于文本串的高效移动。
通过比较文本串和模式串中对应位置的字符,根据部分匹配表中的数值进行跳转,从而快速定位匹配位置。
#### 2.3 匹配成功或失败处理如果匹配成功,返回匹配的起始位置;如果匹配失败,根据部分匹配表中的信息,调整模式串的位置,继续匹配直至完成整个文本串的匹配。
### 3. KMP算法应用场景KMP算法在实际应用中具有广泛的应用场景,特别适用于需要频繁进行字符串匹配的情况。
以下是一些常见的应用场景:- 字符串匹配:在文本编辑器、搜索引擎等软件中,用于查找指定字符串在文本中的位置。
- 数据压缩:在数据压缩算法中,用于查找重复出现的子串,实现数据的高效压缩。
- DNA序列比对:在生物信息学中,用于比对DNA序列,寻找相似性或重复出现的基因片段。
字符串kmp模式匹配算法【字符串kmp模式匹配算法】引言:字符串是计算机科学中非常常见的数据类型,而字符串的模式匹配是一个重要的问题。
模式匹配是指在一个长字符串中寻找一个给定的模式,以确定该模式是否存在于字符串中。
其中,kmp模式匹配算法是一种高效的字符串匹配算法,它在时间复杂度上优于暴力匹配算法,并且在实际应用中有着广泛的应用。
本文将一步一步回答有关kmp模式匹配算法的问题,对其原理、实现细节和应用进行详细阐述。
第一部分:kmp模式匹配算法的原理1. 什么是kmp模式匹配算法?kmp模式匹配算法是一种用于在字符串中寻找给定模式的高效算法。
不同于暴力匹配算法,kmp算法通过预处理匹配字符串的信息,从而在匹配过程中可以跳过一些不必要的字符比较操作,从而提高了匹配效率。
2. kmp模式匹配算法的原理是什么?kmp模式匹配算法的核心是建立一个跳转表,该表存储着模式字符串的任意位置字符不匹配时,下一步应该跳到哪个位置继续匹配。
通过将匹配失败时的跳转表与模式字符串构造出来,可以在匹配过程中根据模式字符串的内容直接跳到有效位置,从而避免了无效的字符比较。
3. 如何构造kmp算法中的跳转表?构造kmp算法中的跳转表需要对模式字符串进行预处理。
预处理过程中,首先计算出每个位置之前最长的相同前缀后缀长度,并将其存储在数组next[]中。
然后,根据next[]数组的内容,构造跳转表。
第二部分:kmp模式匹配算法的具体实现4. kmp算法的具体实现过程是什么?kmp算法的实现过程可以分为两个阶段:预处理阶段和匹配阶段。
预处理阶段用于计算next[]数组,匹配阶段用于根据next[]数组执行匹配。
5. 预处理阶段的具体步骤是什么?a) 首先,根据模式字符串计算next[]数组。
next[i]表示模式字符串中第i个字符之前的子串中最长的相同前缀后缀长度。
b) 初始化计数器i和j为0,然后逐个计算next[i]的值。
如果模式字符串的第i个字符与模式字符串的第j个字符相等,则令next[i] = j+1,并同时递增i和j。
空间复杂度为o(1)的字符串匹配算法
在计算机科学中,字符串匹配是一种经典的问题,即在一个文本串中查找一个给定的模式串出现的位置。
常见的字符串匹配算法有暴力匹配、KMP算法、Boyer-Moore算法等,但它们的空间复杂度都比较高。
本文将介绍一种空间复杂度为o(1)的字符串匹配算法——RK算法。
RK算法是一种基于哈希的字符串匹配算法,它的思路是对文本串和模式串分别计算哈希值,比较两个哈希值是否相等,若相等则进一步检查是否匹配,若不相等则直接跳过。
具体步骤如下:
1. 计算模式串的哈希值。
2. 在文本串中依次取出长度为模式串长度的子串,并计算其哈希值。
3. 比较模式串的哈希值和当前子串的哈希值是否相等,若相等则进一步检查是否匹配,若不相等则继续向后取子串。
4. 若找到匹配的子串,则返回它在文本串中的位置。
需要注意的是,RK算法的哈希函数需要满足以下条件:
1. 哈希值为整数。
2. 相等的字符串具有相等的哈希值。
3. 不同的字符串具有不同的哈希值的概率很大。
常用的哈希函数有求和哈希、位运算哈希、乘法哈希等,选择合
适的哈希函数可以最大程度地减小哈希冲突的概率。
需要注意的是,RK算法并不是万无一失的,存在哈希冲突的概率,但它的时间复杂度和空间复杂度都比较优秀,对于一些简单的应用场景可以使用。
字符串匹配算法的原理和实现随着互联网应用的广泛普及,各种搜索引擎、数据挖掘等技术越来越受到人们的关注。
在很多应用中,我们需要对文本进行匹配,即在一段文本中查找某个字符串是否出现过,或者查找多个字符串在文本中的位置。
这就需要用到字符串匹配算法,本文将介绍字符串匹配算法的原理和实现。
一、暴力匹配算法暴力匹配算法是最朴素的字符串匹配算法,也称为朴素算法或者蛮力算法。
它的原理非常简单,就是从文本的第一个字符开始依次比较,如果匹配失败,则将文本的指针后移一位,开始下一次比较。
具体实现可以用以下代码表示:```int search(string pattern, string text) {int n = text.length();int m = pattern.length();for(int i = 0; i < n - m + 1; i++) {int j;for(j = 0; j < m; j++) {if(pattern[j] != text[i+j]) {break;}}if(j == m) {return i;}}return -1;}```该算法的时间复杂度为O(nm),其中n和m分别是文本和模式串的长度。
当模式串非常短时,该算法的效率还可以接受,但是当模式串很长时,算法效率就会变得很低,甚至比较文本中的每个字符都慢。
因此,我们需要更加快速和高效的算法来实现字符串匹配。
二、KMP算法KMP算法全称为Knuth-Morris-Pratt算法,它是一种比暴力匹配算法更加高效的字符串匹配算法,可以在O(n+m)的时间复杂度内完成字符串匹配。
KMP算法的基本思想是利用匹配失败后的信息来避免无谓的比较,具体过程如下:1.计算模式串的前缀函数(Prefix Function)。
前缀函数的定义是:对于模式串P的每个位置i(0 <= i < m),对应的前缀函数(Pi)表示模式串的第0个位置到第i个位置的最长的,既是最前面的,也是最后面的,与整个模式串P的某个前缀相等的后缀的长度。
KMP算法(字符串匹配)遇到字符串匹配问题,⼀般我就只能想到O(nm)的朴素算法...今天有这样⼀种算法,使得复杂度变为O(n),这就是KMP(烤馍⽚)算法粘⼀个模板题先:给出两个字符串s1和s2,其中s2为s1的⼦串,求出s2在s1中所有出现的位置。
然后本题还要求输出所有s2中字符的前缀数组,现在留下⼀个疑点,前缀数组(这是啥?),先往后看⾸先确定⼀点,就是在进⾏字符串匹配时,会是拿⼀个字符串与另⼀个字符串的⼀部分进⾏⽐较,那么我们有以下称呼(拿本题进⾏举例):s2叫做模式串,s1叫做母串我们先分析朴素算法的原理与弊端:朴素算法是将每⼀个母串字符拿出⽐较,⼀旦不符合就会放弃前⾯匹配的所有信息,重头再来,然⽽KMP不然,KMP就是⼀种"失败为成功之母"的算法,每次在匹配失败时利⽤前⾯信息进⾏更⾼效的匹配,具体的思想需要⽤到这个"前缀数组"那么这是啥呢?先考虑⼀个问题:如何利⽤失败信息,如果匹配失败,我们会放弃当前匹配,然⽽这起码证明前⾯的匹配都是成功的,也就是说,只要我找到模式串前⾯的能与⾃⼰(当前匹配失败之前的⼀个位置)匹配上的⼦串,那么⼀定也能与前⾯匹配,进⾏再次查找,⽽不⽤进⾏朴素算法暴⼒枚举,前缀数组就是保存这样的指针的数组,预处理⼤概是这样的:inline void init(){p[1]=0;int j=0;for(int i=1;i<m;i++){while(j>0&&b[j+1]!=b[i+1]) j=p[j];if(b[j+1]==b[i+1]) j++;p[i+1]=j;}}总体代码是这样的:#include<cstdio>#include<cstring>#include<string>using namespace std;char a[1000005];char b[1000005];int p[1000005];int n,m;inline void init(){p[1]=0;int j=0;for(int i=1;i<m;i++){while(j>0&&b[j+1]!=b[i+1]) j=p[j];if(b[j+1]==b[i+1]) j++;p[i+1]=j;}}inline void find(){int j=0;for(int i=0;i<n;i++){while(j>0&&a[i+1]!=b[j+1]) j=p[j];if(b[j+1]==a[i+1]) j++;if(j==m){printf("%d\n",i-m+2);j=p[j];}}}int main(){scanf("%s%s",a+1,b+1);n=strlen(a+1);m=strlen(b+1);init();find();for(int i=1;i<=m;i++)printf("%d ",p[i]);return 0;}为什么KMP主体与预处理这么像呢?因为预处理本⾝就是我\ \ \ \ 匹配\ \ \ \ \ 我⾃⼰最后就是输出前缀数组了Processing math: 100%。
字符串的模式匹配算法——KMP模式匹配算法朴素的模式匹配算法(C++)朴素的模式匹配算法,暴⼒,容易理解#include<iostream>using namespace std;int main(){string mainStr, str;cin >> mainStr >> str;int i, j, pos = -1, count = 0;for(i = 0; i < mainStr.length(); i++){for(j = 0; j < str.length(); j++, i++){if(mainStr[i] != str[j]){break;}if(j == str.length() - 1){if(count == 0){pos = i - j; //记录第⼀个与str相等的字符串在主串mainStr中的第⼀个字母的下标}count++; //记录与str相等的字符串的数量}}i = i - j; //对i值(主串指针)进⾏回溯操作}cout << "pos=" << pos << ",count=" << count << endl;return 0;}KMP模式匹配算法(C++)KMP模式匹配算法相⽐较朴素的模式匹配算法,减少了主串指针回溯的操作#include<iostream>using namespace std;int main(){string mainStr, str;cin >> mainStr >> str;int i, j, pos = -1, count = 0;int next[256];//计算next数组的数值i = 0;j = -1;next[0] = -1;while(i < str.length()){if(j == -1 || str[i] == str[j]){i++;j++;next[i] = j;}else{j = next[j];}}//查找⼦串的位置和数量i = 0;j = 0;while(i < mainStr.length()){if(mainStr[i] != str[j]){j = next[j];}else{if(j == str.length() - 1){if(count == 0){pos = i - j; //记录⼦串第⼀次的第⼀个字母出现在主串中的位置}count++; //记录在主串中含有⼦串的数量}}i++;j++;}cout << "pos=" << pos << ",count=" << count << endl;return 0;}KMP模式匹配算法改进(C++)改进操作在于计算next数组数值的时候考虑了特殊情况 —— ⼦串形如abcabcabx #include<iostream>using namespace std;int main(){string mainStr, str;cin >> mainStr >> str;int i, j, pos = -1, count = 0;int next[256];//计算next数组的数值i = 0;j = -1;next[0] = -1;while(i < str.length()){if(j == -1 || str[i] == str[j]){i++;j++;if(str[j] == str[i]){next[i] = next[j];}else{next[i] = j;}}else{j = next[j];}}//查找⼦串的位置和数量i = 0;j = 0;while(i < mainStr.length()){if(mainStr[i] != str[j]){j = next[j];}else{if(j == str.length() - 1){if(count == 0){pos = i - j; //记录⼦串第⼀次的第⼀个字母出现在主串中的位置}count++; //记录在主串中含有⼦串的数量}}i++;j++;}cout << "pos=" << pos << ",count=" << count << endl; return 0;}。
位运算经常能做出一些不可思议的事情来,例如不用临时变量要交换两个数该怎么做呢?一个没接触过这类问题的人打死他也想不出来。
如果拿围棋来做比喻,那么位运算可以喻为编程中的“手筋”。
按位的存储方式能提供最大的存储空间利用率,而随着空间被压缩的同时,由于CPU硬件的直接支持,速度竟然神奇般的提升了。
举个例子,普通的数组要实现移位操作,那是O(n)的时间复杂度,而如果用位运算中的移位,就是一个指令搞定了。
KR算法KR算法之前第一章介绍中说是利用哈希,原文这么介绍的。
而我的看法是,哈希只是一个幌子。
这个算法的基本步骤同穷举法一样,不同在于每趟比较前先比较一下哈希值,hash 值不同就不必比较了。
而如果hash值无法高效计算,这样的改进甚至还不如不改进呢。
你想想,比较之前还要先计算一遍hash值,有计算的功夫,直接比都比完了。
KR算法为了把挨个字符的比较转化为两个整数的比较,它把一个m长度的字符串直接当成一个整数来对待,以2为基数的整数。
这样呢,在第一次算出这个整数后,以后每次移动窗口,只需要移去最高位,再加上最低位,就得出一个新的hash值。
但是m太大,导致超出计算机所能处理的最大整数怎么办?不用担心,对整数最大值取模,借助模运算的特性,一切可以完美的进行。
而且由于是对整数最大值取模,所以取模这一步都可以忽略掉。
这是KR算法的代码:#define REHASH(a, b, h) ((((h) - (a)*d) << 1) + (b))void KR(char *x, int m, char *y, int n) {int d, hx, hy, i, j;/* Preprocessing *//* computes d = 2^(m-1) withthe left-shift operator */for (d = i = 1; i < m; ++i)d = (d<<1);for (hy = hx = i = 0; i < m; ++i) {hx = ((hx<<1) + x[i]);hy = ((hy<<1) + y[i]);}/* Searching */j = 0;while (j <= n-m) {if (hx == hy && memcmp(x, y + j, m) == 0)OUTPUT(j);hy = REHASH(y[j], y[j + m], hy);++j;}}我们可以看到,KR算法有O(m)复杂度的预处理的过程,总感觉它的预处理没有反映出模式本身的特点来,导致它的搜索过程依然是O(mn)复杂度的,只不过一般情况下体现不出来,在"aaaaaaaaaaaaaaaaaaaaaaaaa"中搜"aaaaa"就知道KR多慢了。
字符串匹配算法与实际应用案例字符串匹配算法是计算机科学中的一项重要技术,它被广泛应用于实际的软件开发和数据处理中。
本文将介绍字符串匹配算法的概念和原理,并给出一些实际应用案例,旨在帮助读者更好地理解和应用该算法。
一、字符串匹配算法概述字符串匹配算法是指在一个字符串(称为主串)中查找另一个字符串(称为模式串)的过程。
在实际应用中,字符串匹配经常用于查找和处理文本数据、搜索关键字、验证密码等场景。
常见的字符串匹配算法包括暴力匹配算法、KMP算法和Boyer-Moore算法等。
下面将逐一介绍这些算法的原理及其应用。
二、暴力匹配算法暴力匹配算法也称为朴素匹配算法,是最简单直观的字符串匹配方法。
它的基本思想是从主串的第一个字符开始和模式串逐个比较,如果发现不匹配的字符,则通过主串和模式串指针的滑动,重新比较下一组字符,直到找到匹配的子串或主串遍历完毕。
暴力匹配算法的时间复杂度为O(m*n),其中m和n分别为主串和模式串的长度。
虽然该算法的效率相对较低,但适用于简单的字符串匹配场景。
三、KMP算法KMP算法是一种高效的字符串匹配算法,它通过预处理模式串构建一个部分匹配表,从而在匹配过程中避免无效的比较操作,提高匹配效率。
KMP算法的核心思想是利用模式串的局部匹配信息,当主串和模式串发生不匹配时,通过查表找到模式串中下一次比较的位置,从而避免了不必要的比较操作。
KMP算法的时间复杂度为O(m+n),其中m和n分别为主串和模式串的长度。
相比暴力匹配算法,KMP算法在大规模数据处理和搜索引擎等领域具有明显的优势。
四、Boyer-Moore算法Boyer-Moore算法是一种高效的字符串匹配算法,其核心思想是从模式串的末尾开始匹配,通过根据模式串中的字符出现位置提前移动主串的指针,从而跳过无需比较的字符。
Boyer-Moore算法结合了两种启发式策略,即坏字符规则和好后缀规则。
通过预处理模式串构建这两个规则的辅助表格,可以在匹配过程中快速移动主串的指针,从而提高匹配效率。
字符串模式匹配算法:BM、Horspool、Sunday、KMP、KR、AC算法本⽂内容框架:§1 Boyer-Moore算法§2 Horspool算法§3 Sunday算法§4 KMP算算法§5 KR算法§6 AC⾃动机§7 ⼩结§1 Boyer-Moore(BM)算法Boyer-Moore算法原理Boyer-Moore算法是⼀种基于后缀匹配的模式串匹配算法,后缀匹配就是模式串从右到左开始⽐较,但模式串的移动还是从左到右的。
字符串匹配的关键就是模式串的如何移动才是最⾼效的,Boyer-Moore为了做到这点定义了两个规则:坏字符规则和好后缀规则,下⾯图解给出定义:下⾯分别针对利⽤坏字符规则和好后缀规则移动模式串进⾏介绍:坏字符规则1.如果坏字符没有出现在模式字符中,则直接将模式串移动到坏字符的下⼀个字符:(坏字符c,没有出现模式串P中,直接将P移动c的下⼀个位置)2.如果坏字符出现在模式串中,则将模式串最靠近好后缀的坏字符(当然这个实现就有点繁琐)与母串的坏字符对齐:(注:如果模式串P是babababab,则是将第⼆个b与母串的b对齐)好后缀规则好后缀规则分三种情况1.模式串中有⼦串匹配上好后缀,此时移动模式串,让该⼦串和好后缀对齐即可,如果超过⼀个⼦串匹配上好后缀,则选择最靠靠近好后缀的⼦串对齐。
2.模式串中没有⼦串匹配上后后缀,此时需要寻找模式串的⼀个最长前缀,并让该前缀等于好后缀的后缀,寻找到该前缀后,让该前缀和好后缀对齐即可。
3.模式串中没有⼦串匹配上后后缀,并且在模式串中找不到最长前缀,让该前缀等于好后缀的后缀。
此时,直接移动模式到好后缀的下⼀个字符。
Boyer-Moore算法步骤1.对模式⼦串进⾏预处理Boyer-Moore算法实现必须对模式串进⾏预处理,得到坏字符规则和好后缀规则移动的映射表,下⾯代码中MakeSkip是建⽴坏字符规则移动的映射表,MakeShift是建⽴好后缀规则的移动映射表。
字符串匹配算法的研究及其程序实现计算机学院计算机科学与技术专业2007级指导教师:滕云摘要:在字符串匹配算法之中,最古老和最著名的是由D. E. Knuth, J. h. Morris, V. R. Pratt 在1997年共同提出的KMP算法。
直至今日,人们对字符串匹配问题还在进行着大量的研究,以寻求更简单,或者平均时间复杂度更优的算法;学者们在不同的研究方向上,设计出了很多有效的匹配算法。
在现实生活中,串匹配技术的应用十分广泛,其主要领域包括:入侵检测,病毒检测,信息检索,信息过滤,计算生物学,金融检测等等。
在许多应用系统中,串匹配所占的时间比重相当大,因此,串匹配算法的速度很大程度上影响着整个系统的性能。
该论文重点分析了KMP算法的实现原理和C语言实现,并在此基础上提出了改进的KMP算法,使得该算法更方便实用。
关键词:KMP算法;时间复杂度;串匹配;改进;方便使用;String matching algorithm and Implementation of the Program College of Computer Sciences, Computer Science and Technology Professionalgrade 2007, Instructor YunTengAbstractor:Among the string matching algorithm,the oldest and most famous is KMP algorithm co-sponsored by D.E Knuth, J. h. Morris, VR Pratt in 1997. As of today, a lot of research to String matching are still in progress, to seek a more simply or better average time complexity of the algorithm. In different research direction, scholars have designed a lot of valid matching.In real life, the string matching technique is widely used,The main areas include: intrusion detection, virus detection, information retrieval, information filtering, computational biology, financial inspection and so on.In many applications,a large percentage of the time was placed by the string matching, so the string matching algorithms significantly affect the speed performance of the whole system.The paper analyzes the implementation of the KMP algorithm theory and through the C language to achieve it.And we puts forward a modified KMP algorithm in order to makes the algorithm more convenient and practical.Key words:KMP algorithm; Time complexity; String matching; Improved; Easy to use;目录摘要﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒ 1 ABSTRACT﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒ 1第一章引言﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒ 3第一节:字符串匹配研究的目的和意义﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒3第二节:本文的内容和安排﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒ 3第二章串匹配算法的概念与研究现状﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒ 4第一节:字符串匹配的有关概念﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒4第二节:字符串匹配算法的研究现状﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒4第三章KMP算法和BM算法及其改进算法的研究及实现﹒﹒﹒﹒﹒﹒5 第一节:KMP算法的研究及实现﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒5第二节:KMP算法改进及其程序实现﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒8第四章总结和展望﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒12 第一节:总结﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒13第二节:展望﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒13参考文献﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒14致谢﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒14第一章:引言第一节:字符串匹配研究的目的和意义字符串是计算机科学中常见的基本概念,搜索问题也是计算机科学中的基本问题。
字符串匹配算法(KMP算法c语⾔实现)#include<stdio.h>#include<stdlib.h>#include<string.h>/*naive string-matching algorithm,T为原始字符串,P为需要匹配的字符串*/void naiveMatch(char *T,char *P){int lenT,lenP,i,j;lenT=strlen(T);lenP=strlen(P);if(lenT<lenP)/*需要匹配的字符串⽐原始字符串还要长出错*/{perror("input error");return ;}for(i=0;i<(lenT-lenP+1);i++){for(j=0;j<lenP;j++){if(T[i+j]!=P[j])break;}if(j==lenP)printf("string match at place %d\n",i);}}/*kmp预处理需要的匹配串*/void getNext(char *p,int next[]){int len,i,j;len=strlen(p);next[0]=0;for(i=1;i<len;i++){j=next[i-1];while((p[i-1]!=p[j-1])&&(j!=0)){j=next[j-1];// printf("j= %d\n",j);}next[i]=j+1;printf("next[i]=%d\n",next[i]);}}/*kmp字符串匹配算法*/void kmp(char *t,char *p,int next[]){int lent,lenp,i,j;lent=strlen(t);lenp=strlen(p);i=0;j=0;while(i<(lent)){if((j==-1)||(t[i]==p[j])){i++;j++;// printf("i=%d,j=%d\n",i,j);}else{// printf("in else i=%d,j=%d\n",i,j);j=next[j]-1;}if(j==(lenp)){printf("match at place %d\n",i-lenp);}}}int main(){char p[10]="0001";char t[20]="000010001010001";naiveMatch(t,p);/*测试普通字符串匹配算法*/ char p1[10]="abaabcac";char t1[20]="acabaabaabcacaabc";int len=strlen(p1);int *next;next=(int*)malloc(sizeof(int)*len);getNext(p1,next);kmp(t1,p1,next);/*测试kmp算法*/getNext(p,next);kmp(t,p,next);/*测试kmp算法*/}。
本栏目责任编辑:唐一东人工智能及识别技术一种基于KMP 算法思想的字符串匹配算法的研究与实现孙娟红(兰州交通大学博文学院,甘肃兰州730101)摘要:KMP 算法在使用中效率很高,并且在失败匹配之后,不必要重新进行内容字符的匹配,降低了匹配的速度和次数,使得效率大大提高。
在本文中,主要是分析了该算法的优点和实现。
关键词:KMP 算法思想;字符;串匹配算法;研究;实现中图分类号:TP311文献标识码:A文章编号:1009-3044(2019)26-0196-02开放科学(资源服务)标识码(OSID ):当前,我们处于信息化社会,巨大的信息量每天都充斥着人们的生活,不管是在哪个行业和领域中,文本都是承载信息的重要方式,信息的过滤和查找也成了主要的问题。
查找字符串并过滤,如果设计不好那么就使得结果无法满足人们的使用要求。
所以说,高效率的处理过程就显得尤为关键,随着技术的发展逐渐产生了字符串查找和匹配功能。
1BF 算法BF 算法的理论很简单,就是从内容串C 第一个字符起始,到关键字串K 的第一个字符,进行挨个比较,在相等的情况下,进进入第二个字符的比较,之后后移,如果在哪个位置失配,那么就需要对关键字串K 第一个字符和其内容串中的第二个字符再进行匹配和比较,然后类推。
图1匹配过程存在K 为关键字串、C 为内容串,表达式C=“xyxyy ”,K=“xyy ”,在C 中匹配K 。
图1即为整个的匹配的过程。
在图1中,即体现了BF 算法的思想。
BF 算法的思维十分简单和直接,但是也存在很多的不足,例如内容串定位中错误,并且十分容易进行重复的操作。
在失配之后,需要进行二次匹配,在这个过程中,我们需要先采用关键字串第一个字符,将其和内容串第二个字符进行对比,流程可以简化和省略,因为对关键字串进行观察,发现其前边的字符存在不相等性,并且在上轮的对比中,关键字串中的第二个字符于内容串呈现相等的状态,所以说,在关键字串中第一个字符和内容串中第二个字符有着不相等性。
C++实现字符串匹配的KMP算法-电脑资料讲的浅显易懂,便按照他的思路用C++实现了一篇,代码如下:[cpp]include#includeusing namespace std;//计算单次的部分匹配值,如str=="ABCDAB"时返回2int single_match(string str){int n=str.length();string *prefix=new string[n-1]();string *suffix=new string[n-1]();for(int i=0;i!=n-1;++i){for(int j=0;j<=i;++j)prefix[i]+=str[j];for(int k=i+1;k!=n;++k)suffix[i]+=str[k];}int match_num=0;for(int i=0;i<n-1;++i)< p=""></n-1;++i)<>for(int j=0;j<n-1;++j)< p=""></n-1;++j)<>if(prefix[i]==suffix[j])match_num+=prefix[i].length();return match_num;}//对整个字符串,计算其部分匹配表void partial_match_table(string str,int* table){int n=str.length();for(int i=0;i!=n;++i){string sub_str;for(int j=0;j<=i;++j)sub_str+=str[j];int temp=single_match(sub_str);table[i]=temp;}}// KMP算法int Knuth_Morris_Pratt(string str1,string str2,int *table) {int n1=str1.length();int n2=str2.length();int i=0;while(i<n1-n2){< p=""></n1-n2){<>int j=0;while(j<n2){< p=""></n2){<>if(str1[i+j]==str2[j])++j;elsebreak;}if(j==n2)break;else if(j==0)++i;elsei+=j-table[j-1];}if(i>n1-n2)return -1;return i;}int main(){string str1("BBC ABCDAB ABCDABCDABDE");string str2("ABCDABD");int n=str2.length();int *table=new int[n];for(int i=0;i<n;++i)< p=""></n;++i)<>cout<cout<<endl;< p=""></endl;<>cout<<knuth_morris_pratt(str1,str2,table)<<endl;< p=""></knuth_morris_pratt(str1,str2,table)<<endl;<> return 0;}#include#includeusing namespace std;//计算单次的部分匹配值,如str=="ABCDAB"时返回2 int single_match(string str){int n=str.length();string *prefix=new string[n-1]();string *suffix=new string[n-1]();for(int i=0;i!=n-1;++i){for(int j=0;j<=i;++j)prefix[i]+=str[j];for(int k=i+1;k!=n;++k)suffix[i]+=str[k];}int match_num=0;for(int i=0;i<n-1;++i)< p=""></n-1;++i)<>for(int j=0;j<n-1;++j)< p=""></n-1;++j)<>if(prefix[i]==suffix[j])match_num+=prefix[i].length();return match_num;}//对整个字符串,计算其部分匹配表void partial_match_table(string str,int* table){int n=str.length();for(int i=0;i!=n;++i){string sub_str;for(int j=0;j<=i;++j)sub_str+=str[j];int temp=single_match(sub_str);table[i]=temp;}}// KMP算法int Knuth_Morris_Pratt(string str1,string str2,int *table) {int n1=str1.length();int n2=str2.length();int i=0;while(i<n1-n2){< p=""></n1-n2){<>int j=0;while(j<n2){< p=""></n2){<>if(str1[i+j]==str2[j])++j;elsebreak;}if(j==n2)break;else if(j==0)++i;elsei+=j-table[j-1];}if(i>n1-n2)return -1;return i;}int main(){string str1("BBC ABCDAB ABCDABCDABDE");string str2("ABCDABD");int n=str2.length();int *table=new int[n];for(int i=0;i<n;++i)< p=""></n;++i)<>cout<cout<<endl;< p=""></endl;<>cout<<knuth_morris_pratt(str1,str2,table)<<endl;< p=""></knuth_morris_pratt(str1,str2,table)<<endl;<> return 0;}代码的缺点是对字符串的处理太过生硬,,电脑资料《C++实现字符串匹配的KMP算法》(https://www.)。
字符串模式匹配KMP算法字符串模式匹配指的是,找出特定的模式串在⼀个较长的字符串中出现的位置。
朴素的模式匹配算法很直观的可以写出下⾯的代码,来找出模式串在⼀个长字符串中出现的位置。
1: /*2: 朴素的模式匹配算法3: 功能:字符串的模式匹配4: 参数:5: s:⽬标串6: p:模式串7: pos:开发匹配的位置8: 返回值:9: 匹配成功,返回模式串在⽬标串的其实位置10: 匹配不成功,返回-111: */12: int match(const char * s ,const char * p,int pos){13: int i = pos ;14: int j= 0 ;15: while(s[i] != '\0' && p[j] != '\0') {16: if(s[i] == p[j]) {17: i ++ ;18: j ++ ;19: }else {20: i = i - j + 1;21: j = 0 ;22: }23: }24:25: if(p[j] == '\0')26: return i - j ;27: else28: return -1 ;29: }上⾯的代码,s就是⽬标串,p是模式串,pos指定从s的什么位置开始匹配p。
其实现思想也很简单:当s[i] == p[j]时,⽬标串和模式串的指针都向后移动⼀位,进⾏匹配。
⽽当s[i] != p[j]时,即匹配不成功时,将⽬标串和模式串的指针同时回溯,j = 0 ⽽⽬标串的指针i则回溯到这轮开始的下⼀个位置。
朴素的模式匹配的算法复杂度是O( (n-m+1) * m) n为⽬标串的长度,m为模式串长度。
从其实现思想上可以很容易的看出,造成该算法低效的地⽅是在,匹配不成功时主串和模式串的指针回溯上。
有没有⼀种算法,当模式串和主串的匹配不成功时,不⽤进⾏指针的回溯,直接进⾏下⼀轮的匹配?KMP算法理解在朴素的字符串模式匹配算法上,当遇到主串和模式串的字符不能匹配成功时,不论已经匹配了多少字符都要进⾏指针回溯,再开始下⼀轮的匹配。
独树⼀帜的字符串匹配算法——RK算法参加了雅虎2015校招,笔试成绩还不错,谁知初⾯第⼀题就被问了个字符串匹配,要求不能使⽤KMP,但要和KMP⼀样优,当时瞬间就呵呵了。
后经过⾯试官的⼀再提⽰,也还是没有成功在⾯试现场写得。
现将该算法记录如下,思想绝对是字符串匹配中独树⼀帜的字符串匹配存在长度为n的字符数组S[0...n-1],长度为m的字符数组P[0...m-1],是否存在i,使得S i S i+1...S i+m-1等于P0P1...P m-1,若存在,则匹配成功,若不存在则匹配失败。
RK算法思想假设我们有某个hash函数可以将字符串转换为⼀个整数,则hash结果不同的字符串肯定不同,但hash结果相同的字符串则很有可能相同(存在⼩概率不同的可能)。
算法每次从S中取长度为m的⼦串,将其hash结果与P的hash结果进⾏⽐较,若相等,则有可能匹配成功,若不相等,则继续从S中选新的⼦串进⾏⽐较。
假设进⾏下⾯的匹配:S0S1...S i-m+1S i-m+2...S i-1S i S i+1...S n-1P0P1P m-2P m-1情况⼀、hash(S i-m+1...S i) == hash(P0...P m-1),此时S i-m+1...S i与P0...P m-1有可能匹配成功。
只需要逐字符对⽐就可以判断是否真的匹配成功,若匹配成功,则返回匹配成功点的下标i-m+1,若不成功,则继续取S的⼦串S i-m+2...S i+1进⾏hash情况⼆、hash(S i-m+1...S i) != hash(P0...P m-1),此时S i-m+1...S i与P0...P m-1不可能匹配成功,所以继续取S的⼦串S i-m+2...S i+1进⾏hash可以看出,不论情况⼀还是情况⼆,都涉及⼀个共同的步骤,就是继续取S的⼦串S i-m+2...S i+1进⾏hash。
如果每次都重新求hash结果的话,复杂度为O(m),整体复杂度为O(mn)。