字符串科技总结之KMP详解

定义一个东西
字符串科技总结之KMP详解_第1张图片
Border的定义说人话就是对于一个字符串,前后缀相等的长度的字符串,比如BAAB,Border的有效取值是1,2的字符串,因为B=B,BA = BA,注意这里前后缀等的长度是可以让前后缀相等的地方重叠的,比如AAA,Border的可供选择的数字是1,2的字符串,但是不能取到3,Border长度必须严格小于字符串总长。
KMP的next[i]数组的含义就是字符串[1,i]的最大Bborder.
首先关于next[i]也就是next[i-1]延伸过来的。
要找到[1,i]的字符串的最大前后缀相等的串,
字符串科技总结之KMP详解_第2张图片
蓝色部分为[1,i-1]的Border那么直接判断后一个能不能直接进行延伸,那么我们就可以知道能不能从上一个Border去拓展得到。如果可以拓展为什么说这个Border就是当前[1,i]的最大Border?
因为如果不是最大的Borde那么我们必然在[1,i-1]的字符串可以找到一个比蓝色笔更长的前后缀相等的字符串,然后在进行延伸拓展得来。但是这个字符串与next数组的定义相违背,因为我们的next数组就已经是最大的Border了,所以在[1,i-1]里面不存在比蓝色笔更大的Border所以当前延伸拓展的Border就是最大的Border。
下一个问题,如果我们在next[i-1]所代表的那个最长前后缀无法延伸拓展,那要怎么办?
字符串科技总结之KMP详解_第3张图片
当前要填的是next[9],已知next[8] = 3,即字符串[1,3]与[6,8]是相同的。如果我们发现字符4与字符9是不匹配的,那么则无法延伸拓展,我们需要找[1,8]次小的Border,[1,8]的最大Border我们无法延伸,则去判断次大的Border能否延伸,怎么获得[1,8]次大的Border?次打的Border就是next[3],因为next[8] = 3,则next[3]的数值就是次大的Border,为什么呢?首先蓝色笔部分代表的就是[1,8]的最大Border,然后,next[3] = 1,则紫色比的地方就是[1,3]的Border,即字符1等于字符3.但是在由于我们已知的[1,3] = [6,8]就可得
字符1 = 字符3 = 字符6 = 字符8.我们需要的也就是字符1 = 字符8,这也就是[1,8]的一个Border,为什么这个字符串是次小的?其实和上面说最大的那个证法是差不多了,就不展开了。
我们通过不断企图延伸上一个位置的Border,用上一个位置的最大,次大,第三大。。。。。去找到一个我们能延伸的点(当然如果不能延伸自然Border长度就是0)。
其实上面的例子也表名Border的延伸性。
我们在两个字符串去匹配的时候利用的kmpnext数组就是利用的前后缀相同的特点去优化匹配过程。

 void get_nex() {
	int j = 0; next_[1] = 0;
	len_node = strlen(node + 1);
	for (int i = 2; i <= len_node; i++) {
		while (j && node[i] != node[j + 1]) { j = next_[j]; }
		if (node[j + 1] == node[i])j++;
		next_[i] = j;
	}
}

这就是大家经常看见的KMP的板子了,最关键的跳next的含义当你理解了上文其实也就知道了为什么要那样子跳了。所以其实在两个字符串匹配的时候要怎么写也很清楚了,你已经匹配上了多少个字符,如果不匹配就跳next,也就是跳下一个最大的Border。

好了接下来我们要做一个大胆的举动。
当我们把i和next[i]连一条边会发生什么。首先一个点只会连一条边,除了[1,i]还多了一个节点0,所以最后会变成一棵树。
这棵树的作用是什么呢?
每个节点往根节点走的路径代表着什么?根据上文的next的过程其实我们可以知道,节点往根节点所经过的路径就是节点i的Border的所有可行选择。
树上我们就可以进行很多的操作,比如如果询问节点i和节点j的公共最长Border呢?就是节点i和节点j的LCA,那个节点的编号也就是最长的公共Border。假设你要询问某一个前缀出现的次数呢?就是字符串[1,i]的出现次数,其实可以发现就是在这颗树上的i所在节点的子树大小。因为在他子树里面的每一个节点都是含有i这个节点的Border,也就是都含有[1,i]这个串。
这颗树能做的操作还有很多,就不一一说明,但是难题KMP基本上大部分是用到了这颗树。
模板题洛谷P5829失配树

关于KMP有一个很重要的结论字符串长度-Border长度=周期
分两种情况。
(1)Border没有重叠部分
字符串科技总结之KMP详解_第4张图片
这是显然是一个周期。

(2)情况2是Border是重叠的
字符串科技总结之KMP详解_第5张图片
由于Border的定义我们易得紫色笔部分是相同的,问题就在于,红色括号哪里如何证明相同
字符串科技总结之KMP详解_第6张图片
同样由于Border定义可得1 = 2,然后因为1=3(1,3是相同的部分)所以3 =2.
这样我们就证明了两种情况下的字符串长度-Border长度就是一个周期长度。
接下来很重要!!!**最小周期显然等于最大Border长度(因为毕竟等式第一项是常数),其他的周期呢?次大Border,第三大Border,他们与字符串长度相减也是会获得一个周期,这么减下来的几个周期长度的递增的。**所以当你要求字符串的所有周期也可以通过跳next的方式来获得。一定一定不要想当然的以为用最小周期每次长度减小1就是周期噢,这可以举出反例的,周期要利用跳next获得的数值来变化,不能直接-1.

最后的最后,推荐一个视频。
视频链接
觉得讲的特别详细还有很多的例题。怎么来吹他呢,我感觉就是看完视频后KMP一看就会题目一写就A,秒切KMP难题。

你可能感兴趣的:(字符串)