kmp算法
本人理解敲出来的,有些长,如果想要理解请认真看完
那么如何进行匹配呢,若文本串str1为aabaaaabaaf,模式串str2为aabaaf
上面求出来aabaaf的next表为 010120
指针 i = 0, j = 0 (i为文本串指针, j为模式串指针)
如果想要搞懂一定要,一定要手写一下这个比较流程你会很清晰。
next数组,并不需要求出所有的子串,我们可以看到aabaa
前缀[a,aa,aab,aaba]
后缀[a,aa,baa,abaa]
最大相符的是aa,但前面a也相符,所以最大相符前面的必然相符,就是一个循环对半对比,知道不相等就退出,不相等的前一个位置的子串数目就是最大个数,比较次数为子串索引max / 2
比较时候为了方便每个位置的前缀值=前一个位置,第一个位置为-1
所以:当j = -1时候代表该元素没有办法移动到别的前缀,那么i++,j++(j=0)即下一个位置的元素与模式串第一个元素比较
当j不等于-1时候,i和j上的元素不相等则,j改为前缀值进行比较,相等i++,j++
如图
int getlength(T& array) {
return (sizeof(array) / sizeof(array[0]));
}
int kmp(string str1, string str2) {
int n1 = str1.size();
int n2 = str2.size();
int* next = new int[n2];
next[0] = -1;
//获取前缀表
for (int i = 0; i < n2-1; i++) {
int z = i; int x = 0;
int num = (i + 1) / 2;
for (int j = 0; j < num; j++) {
if (str2[j] != str2[z]) {
break;
}
else {
z--;
x++;
}
}
next[i+1] = x;
}
for (int i = 0; i < n2; i++) {
cout << next[i];
}
//kmp
int i = 0; int j = 0;
while (i < n1 && j < n2) {
if (j == -1 || str1[i] == str2[j]) {
i++;
j++;
}
else {
j = next[j];
}
}
if (j >= n2) {//匹配成功,返回子串的位置
return i - n2;
}
return -1;
}
int main() {
string str1, str2;
str1 = "anjabaabaafxdf";
str2 = "aabaaf";
cout << endl << kmp(str1, str2);
}