一、
我们先看下面这个算法当比较到不匹配的时候
模式串后移一位,并且让比较指针回去,这就叫做指针的回溯,回溯就是造成这个简单算法效率比较低的原因
这种是朴素模式匹配算法,时间复杂度比较高
int index(Str str,Str substr)
{
int i=1,j=1,k=1;//串从数组下标为1的位置开始存储,因此初值为1
while(i<i<=str.length && j<=substr.length)
{
if(str.ch[i]=substr.ch[j])
{
++i;
++j;
}
else
{
j=1;
i=++k;//匹配失败,i从主串的下一个位置开始,k中记录了上一次的起始位置
}
}
if(j>substr.length)
{
return k;
}
else
{
return 0;
}
}
下面是一个简单的例子:
KMP算法就是从主串中找到与之相匹配的字串,KMP算法讲究的是一个快
我们回到刚刚位置不匹配的位置
第一比较指针左边上下两个字串是匹配的
而且这个模式串中有公共前后缀
接下来是KMP算法的核心要点,使得公共前后缀里的前缀移动到了原来后缀的位置
这样移动可以保证当前比较指针所在的位置左边的串上下是匹配的
当比较X的时候与主串不匹配的时候,只需要找出X之前的公共前后缀然后执行上述操作
如果模式串中有多个公共前后缀,那么我们就要取最长的那一个
接着我们继续移动
发现此时的移动后的模式串超出了主串的范围,所以就意味着匹配失败
再看一个例子
移动后就发现了匹配的情况
二、
假如第一个位置发生了不匹配的情况,让数组下标为1的字符与主串中的下一位进行比较
假如第二个位置发生了不匹配的情况,发现箭头左边的字串长度只有一,而我们要求的是公共前缀的长度要小于这个字串的长度,此时的公共前后缀的长度就为0了
指针左边的长度就是公共前后缀的长度,为0
这里的数组下标相当于公共前后缀的长度+1
然后就要引出一个next数组
假设求串′ababaaababaa′的next数组
1、
2、前两个规定为0、1,上面述说了
3、比较第三位的时候他们的公共前后缀为0
next数组下标为1
4、比较第四位的时候,他们的公共前后缀为1 即a
next数组下标为2
5、比较第五位的时候,他们的公共前后缀为3 即ab
next数组下标为3
6、比较第六位的时候,他们的公共前后缀为aba
依次类推,不再赘述
三、求解next数组
上面的模式串红色部分为公共后缀
下面的模式串红色部分为公共前缀
长度为t-1
当前指针指向的那个是t
那么下一步就可以比较t+1的那个位置
如果Pj=Pt的时候
两个相加之后会使得他们的公共前后缀加1
也就是这一段的公共前后缀