个人微信公众号Geek_Zhai
核心思想:
KMP 算法就是在试图寻找一种规律:在模式串和主串匹配的过程中,当遇到坏字符后,对于已经比对过的好前缀,利用字符串的特点,尽可能多滑动几位,提高效率(听起来好像和BM算法差不多)
算法讲解:
KMP算法与BM算法最大的不同在两点
1、从前往后匹配
2、利用好前缀的前后缀子串最长匹配规则
如下图
与BM算法一样,这里的前后缀最长匹配长度,我们也可以提前计算出来保存好。
代码如下
void createNext(string& b,int m)
{
next = new int[m];
next[0]=-1;
int k =-1;
for (int i = 1; i < m; ++i)
{
while(k != -1 && b[k+1] != b[i]){
//此处是当发生当前前缀子串与后缀子串的最后一个字符不匹配时候
//不停的缩短子串长度k,直至b[k+1] == b[i]
//因为next数组里面保存的都是匹配的子串的长度,所以可以保证当b[k+1] == b[i]的时候就是匹配的最长子串
k = next[k];
}
if(b[k+1] == b[i])
{
k++;
}
next[i] = k;
}
}
总结:
完整代码如下:
class Solution
{
public:
Solution()
{
}
void createNext(string& b,int m)
{
next = new int[m];
next[0]=-1;
int k =-1;
for (int i = 1; i < m; ++i)
{
while(k != -1 && b[k+1] != b[i]){
//此处是当发生当前前缀子串与后缀子串的最后一个字符不匹配时候
//不停的缩短子串长度k,直至b[k+1] == b[i]
//因为next数组里面保存的都是匹配的子串的长度,所以可以保证当b[k+1] == b[i]的时候就是匹配的最长子串
k = next[k];
}
if(b[k+1] == b[i])
{
k++;
}
next[i] = k;
}
}
int KMP(string src,string dst)
{
int j =0;
for(int i =0;i<src.length();++i)
{
while( j > 0 && src[i] != dst[j])
{
//此处通过提前准备的前后缀最长匹配字符串计算滑动距离
//j是坏字的下标
j=next[j-1]+1;
}
if(src[i] == dst[j])
{
j++;
}
if(j==dst.length())
{
return i-dst.length()+1;
}
}
}
int *next;
};