KMP之所以在竞赛中常见,并不是因为它用来匹配字符串,而是用它的next数组,为了介绍它,我们先讲讲最长公共前缀
最长公共前缀 我们拿字符串ababcab作为例子
string a b a b c a b len 0 0 1 2 0 1 2 这里所表达的是,例如取第3、4个字符”ab”,这个子串与前缀完全匹配,且它的长度是2,所以就记录2,而第3、4、5个字符”abc”与前缀不能完全匹配,就记作0,含义就这么简单,而且你会发现,计算b的时候,可以根据它所匹配的字符的偏移来,b如果是匹配的,就找到匹配的那个字符是数组中的第几个,它是第二个,所以填2进去。我们再来看更复杂的例子
string a b a c a b a b len 0 0 1 0 1 2 3 2 最后那个字符不匹配的时候,1是怎么计算出来的呢,直接重新计算当然也可以,但就出现重复计算了。我们考虑一下匹配过程,在前面的字符a的时候,前后各一个指针,像这样
string a b a c a b a b len 0 0 1 0 1 2 3 ? pointer ^ ^ 然后两个a匹配,arr[6] = pointer1 - arr 得到3,然后两指针一起移动
string a b a c a b a b len 0 0 1 0 1 2 3 ? pointer * ^ ^ 这时候,不匹配,那么前一个指针上一次指向的是arr[2]的位置,即图上*的地方,值是1,这个值如果是p,那就移动到arr[p]的地方,所以就移动到arr[1]的地方,本质上就是找到前一个匹配此后缀的位置,即
string a b a c a b a b len 0 0 1 0 1 2 3 2 pointer ^ ^ 然后再尝试匹配,这次匹配上了,然后前一指针指向第二个元素,所以赋值2