您的位置:首页 > 编程语言 > C语言/C++

KMP算法研究(一)

2016-03-29 23:07 375 查看

 变量定义:

      T :主串

     W:模式串

     next[i]:模式串中从第1个字符到第i+1个字符构成的子串的最大前缀后缀相等数目。

1.KMP算法简介

  KMP算法主要是功能便是判断模式串是否出现在主串中,并找出相应的出现位置。而在常规的暴力破解算法中,通常采用顺序比对的方法进行查找,也就是将模式串依次与主串的第1、2、3....个字符比较,直到找出与模式串相等的子串,这样就会造成信息的浪费。而在KMP算法中,对于每一个模式串我们会事先计算出模式串的内部匹配信息,在匹配失败时最大的移动模式串,以减少匹配次数。

2.KMP算法比较过程

假定主串T:a b a c a a b
a c a b a 

   模式串M:a b a c a b

第一次比较:

Tabacaabacaba
Mabacab      
第二次比较:

Tabacaabacaba
M    abacab  
第三次比较:

Tabacaabacaba
M     abacab 
  第一次比较中,在T[5]与W[5]出现了不匹配,而T[0]~T[4]是匹配的,现在T[0]~T[4]就是上文中说的已经匹配的模式串子串,现在移动找出最长的相同的前缀和后缀并使他们重叠.而对于移动的步数则由以下公式确定:
移动步数=上一步查找中相同的字符个数 -M中第一个不匹配字符的前一个字符的最大前缀后缀数

注解:

首先,前缀和后缀的解释如下



如:a
b a b a b c

       后缀:通俗地说就是所有包含了尾部字符的字串,就是一个后缀,如c
,bc,abc,都是;
       前缀:当然是包含了第一个字符的子串了.

其次,就是在步数的移动上。在上一步的比较中,假设相等的子串为:a b a c a,则该子串的最大前缀后缀数为1,也就是前缀与后缀相等时,最大的长度为1.也就是说,在主串中从i到i+4,在模式串中从0到4,是分别对应相等的,在下次的移动中,为了尽可能多地增大移动步数,就将模式串中移动到主串该次前缀的位置,重新开始比较。
具体实现代码如下:(时间很晚了,注释就明天起来再加)
#include<iostream>
#include<string>

using namespace std;
void getNext(string W, int *next);
void KMPsearch(string T,string W,int *next);
int main(void){
int n = 0;
string T,W;
cin >> T;
cin >> W;
n = W.length();
int *next=new int
;
getNext(W,next);
KMPsearch(T,W,next);
delete []next;
return 0;
}
void KMPsearch(string T, string W, int *next){
int m = 0, n = 0, i = 0, j = 0;
n = T.length();
m = W.length();
while (i < n){
if (T[i] != W[j] && j != 0){
i = i + j - next[j - 1];
j = 0;
}
if (T[i] != W[j] && j == 0){
i = i + 1;
}
if (T[i] == W[j]){
i++;
j++;
}
if (j == m){
cout << "Location: " << i - m + 1<< endl;
return;
}
}
}

void getNext(string W, int *next){
int m = W.length();
next[0] = 0;
for (int i = 1; i < m; i++){
if (W[i] == W[next[i - 1]]){
next[i] = next[i - 1] + 1;
}
else{
next[i] = 0;
}
}
/*for (int i = 0; i < m; i++){
cout << next[i] << endl;
}*/
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  KMP C++