KMP算法
1.开挂传送门:点击打开链接
这个算法理解起来有点难受,建议看下简单的串模式匹配算法 BF算法 刷下经验,如上链接。
2.优化匹配算法:
相比于Brute-Force(BF算法),每当一趟匹配出现字符不等时,不需要回溯i指针(目标串指针),并且模式串指针j将从已经得到的部分匹配模式尽可能后移,从而降低时间消耗。
3.时间复杂度:
O(n+m)(BF算法为O(n*m))
4.个人理解
对于这个算法说实话我看了两个小时才懂得皮毛,写这篇文章先收录这个算法,后面我会出更详细的介绍(希望不是flag)
这个算法包括两个部分:
1)对模式串进行模式匹配并结果写入Next数组
这个部分是为了完成在目标串和模式串不匹配时让模式串指针尽可能后移,而后移的前提:
Str(0~k-1)=Str(j-k+1~j-1)
所以其实这部分也相当于在求出模式串每个字符前面的k个字符,与从Str[0]开始的字符相同的个数,并将结果储 存在Next相应位置。
比如Next[5]=2的意思时但匹配到5的时候字符不相等,这个时候因为指针5前面有一个字符和开头字符相等,则不 需要匹配第一个字符,直接从第二个字符开始匹配。
2)目标串和模式串完成匹配并返回匹配结果
需要用到前面的Next数组,完成对模式串的“尽可能右移”。
贴代码
#include<iostream> #include<string> using namespace std; void Pre_View_Next(const string& Str, int *Next)//自身模式匹配 { int k = -1, j = 0; Next[0] = -1; while (j < Str.length()-1) { if (k == -1 || Str[j] == Str[k]) { k++; j++; Next[j] = k; } else k = Next[k]; } } int Load_KMP(const string& Primer_Str, const string& Str, int *Next)//主串Primer_Str同模式串Str匹配 { int i = 0, j = 0; int len1 = Primer_Str.length(), len2 = Str.length(); while (i < len1 && j < len2) { if (j == -1 || Primer_Str[i] == Str[j]) { i++; j++; } else j = Next[j]; } if (j == len2) return i-len2; else return 0; } int main() { int *Next; string Pre_Str, Str; cin >> Pre_Str >> Str; Next = new int[Str.length()]; Pre_View_Next(Str, Next); /*for (int i = 0; i < Str.length(); i++) cout << Next[i] << endl;*/ cout << Load_KMP(Pre_Str, Str, Next) << endl; delete Next; return 0; }