kmp算法
字符串快速匹配算法,找到模式串P在主串T种第一次出现的位置
规定指针i和j,初始化i指向主串首个字符,j指向模式串首个字符
kmp算法,逐个字符匹配,匹配成功,i++,j++
匹配失败,如果是模式串首字符匹配失败,i后移
反之,j回溯,回溯到的位置是匹配成功的字符串的最长相同前缀后缀中,后缀的起始位置
记录匹配失败后跳转位置的数组是next数组,数组长度等于模式串长度
求next数组的方法:
void getnext(seqstring *p, int next[])
{
int i, j;
next[0] = -1;
i = 0; j = -1;
while (i < p->length)
{
if (j == -1 || p->str[i] == p->str[j])
{
++i;
++j;
next[i] = j;
}
else
j = next[j];
}
for (i = 0; i < p->length; i++)
printf("%d ", next[i]);
}
理解
先膜拜一下大佬的博客
https://www.cnblogs.com/yjiyjige/p/3263858.html
读了大佬的博客简单讲一下我个人的一点看法:
1.
kmp算法好在哪里?
对于长度为n的子串p
分治,匹配失败的原因有几种?
p种,第1,2,3。。。个字符匹配失败,但是匹配过程种可能一直犯同一种错误,如果每一次犯错误都视为一个新的错误来处理那就太笨了,所以对于每一类错误要提前分析好解决办法
2.当理解了这一个最基本的想法之后再去理解具体的处理一类错误的方法。
关键:匹配失败后回溯的位置与主串无关
这个无关并不是真正的无关,而是因为可选择的回溯范围其实就是子串自己匹配成功的部分。子串是提前可见的,我们直接子串而不是直接考虑主串就可以提前定义处理方法,并且这个方法可以适用于任何一个主串。
现在再来看这样一个方法,会发现我只需要对子串定义一下移动的方法,也就是用next[]保存回溯的位置就可以直接对任意一个主串使用啦,一劳永逸!