一:在介绍KMP算法之前,先介绍一下BF算法
(1)BF算法(传统的匹配算法,也是最简单的算法)
BF算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串P的第一个字符进行匹配,若相等,则继续比较S的第二个字符和P的第二个字符;若不相等,则比较S的第二个字符和P的第一个字符,依次比较下去,直到得出最后的匹配结果。其实在上面的匹配过程中,有很多比较是多余的。在第五趟匹配失败的时候,在第六趟,i可以保持不变,j值为2。因为在前面匹配的过程中,对于串S,已知s0s1s2s3=p0p1p2p3,又因为p0!=p1!,所以第六趟的匹配是多余的。又由于p0==p2,p1==p3,所以第七趟和第八趟的匹配也是多余的。在KMP算法中就省略了这些多余的匹配。
(3)BF代码:
int BFMatch(char* ori,char *des) { int i,j; i = 0; while(*(ori+i)!='\0') { j = 0; while(*(ori+i)!='\0'&&*(des+j)!='\0'&&*(ori+i)==*(des+j)) { i++; j++; } if(*(des+j)=='\0') return i-j;// 返回匹配成功后的src中的开始下标 i = i-j+1;// 回溯到,这次匹配的src中的开始位置的下一个位置 } return -1; }
二:KMP算法
(1)KMP算法之所以叫做KMP算法是因为这个算法是由三个人共同提出来的,就取三个人名字的首字母作为该算法的名字。其实KMP算法与BF算法的区别就在于KMP算法巧妙的
消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(mn)下降到O(m+n)。
在KMP算法中,为了确定在匹配不成功时,下次匹配时j的位置,引入了next[]数组,next[j]的值表示P[0...j-1]中最长后缀的长度等于相同字符序列的前缀。
对于next[]数组的定义如下:(2)KMP算法通过next数组可以知道目标串中下一个字符是否有必要被检测,这个next数组就是用所谓的“前缀函数(一般数据结构书中的getNext函数)”来存储的。
这个函数能够反映出现失配情况时,系统应该跳过多少无用字符(也即模式串应该向右滑动多长距离)而进行下一次检测
一是这个前缀函数的求法。
二是在得到前缀函数之后,怎么运用这个函数所反映的有效信息避免不必要的检测。
下面介绍《部分匹配表》是如何产生的。
首先,要了解两个概念:"前缀"和"后缀"。 "前缀"指除了最后一个字符以外,一个字符串的全部头部组合;"后缀"指除了第一个字符以外,一个字符串的全部尾部组合。"部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。以"ABCDABD"为例,
- "A"的前缀和后缀都为空集,共有元素的长度为0;- "ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。
(3) 代码如下:
#include <iostream> #include <cstring> using namespace std; const int MAX_SIZE = 64; void getNext(char *p,int next[]) { int j,k; next[0] = -1; j = 0; k = -1; while(j<strlen(p)) { if(k==-1 || p[j]==p[k]) { j++; k++; next[j] = k; } else k = next[k]; } int i; for(i=1;i<=j;i++) cout << next[i] << ","; } int KMPMatch(char *s,char *p) { int next[MAX_SIZE]; int i,j; i = 0; j = 0; getNext(p,next); while(s[i]!='\0') { if(j==-1 || s[i]==p[j]) { i++; j++; } else { j = next[j];// 消除指针回溯 } if(p[j] == '\0') return i-j; } return -1; } int main() { char ori[MAX_SIZE],des[MAX_SIZE]; cout << "请输入两个字符串进行匹配:" << endl; cin >> ori >> des; //cout << "匹配结果:" << BFMatch(ori,des) << endl; cout << "匹配结果:" << KMPMatch(ori,des) << endl; return 0; }
原文地址:http://blog.csdn.net/u010700335/article/details/40425451