因为一本通少了一些算法,所以我就自行补充了一些东西上去。
EXKMP也就是扩展KMP,是一种特别毒瘤的东西
EXKMP确实很难,我理解他的时间与AC机的时间差不多,而且还很难记,因此一学会就马上写博客了QAQ
定义
EXKMP就是解决这种问题的。
先讲两个数组的定义(默认所有数组从1开始):
ex数组,代表A(主串)的从第i位与B(子串)的最长相同前缀。
next数组,代表B(子串)的从第i位与B(子串)的最长相同前缀。
算法思想
注:所有字符串下标从1开始
首先,假定已经匹配的ex数组位置为1~a,next数组全部匹配好了(next数组的匹配方式跟ex数组的匹配方式大致相同,后面会讲,不用担心)。
首先,我们定义一个 p p p,代表 m a x ( i + e x i − 1 ) ( i ∈ [ 1 , a ] ) max(i+ex_{i}-1)(i\in [1,a]) max(i+exi−1)(i∈[1,a]),也就是目前在主串中匹配到的最远的位置,同时设能使p最大的 i i i为 b b b,设目前要匹配 k k k的位置。
首先,我们知道,当 a < = p a<=p a<=p时,那么我们可以知道 A b → p = B 1 → ( p − a + 1 ) A_{b\rightarrow p}=B_{1\rightarrow (p-a+1)} Ab→p=B1→(p−a+1)。
注:至于 a = = p + 1 a==p+1 a==p+1的情况仅当 e x a = 0 ex_{a}=0 exa=0并且以前的 i + e x i − 1 i+ex_{i}-1 i+exi−1都没有超过 a − 1 a-1 a−1,且在这种情况下,在后面会讲到,将被归类在 k + L > = p k+L>=p k+L>=p中 k > p k>p k>p的情况,不会造成任何任何影响,后面会讲,无需着急,同时不会有 a > p − 1 a>p-1 a>p−1的情况。
注:上面是B串,下面是A串,绿色部分为相等部分。
那么,我们去掉一起从开头去掉 k − b k-b k−b长度的字符串,即为 A k → p = B ( k − b + 1 ) → ( p − a + 1 ) A_{k\rightarrow p}=B_{(k-b+1)\rightarrow (p-a+1)} Ak→p=B(k−b+1)→(p−a+1)(紫色部分)
注:为什么 k k k挨着 a a a?因为 k = a + 1 k=a+1 k=a+1,这里为证明方便,多设一个k。
但是,我们并不知道从A串从 k k k开始的地方与B串从 1 1 1开始的地方有什么瓜葛?
这时候,我们需要一员大将:设 L = n e x t k − b + 1 L=next_{k-b+1} L=nextk−b+1,没错,我们知道了 A k → p = B ( k − b + 1 ) → ( p − a + 1 ) A_{k\rightarrow p}=B_{(k-b+1)\rightarrow (p-a+1)} Ak→p=B(k−b+1)→(p−a+1),那么我们就可以找出从 B 1 B_{1} B1开始最长可以与 B ( k − b + 1 ) B_{(k-b+1)} B(k−b+1)相等多少,就是next数组。
这时候,有了两种情况:
先设 n o w = k + L − 1 now=k+L-1 now=k+L−1。
- now<p
注:上面是B串,下面是A串,粉色框框与绿色框框为相等部分。
我们发现,三个蓝色部分: B ( n o w + 1 ) , A ( L + 1 ) , A ( k − b + L + 1 ) B_{(now+1)},A_{(L+1)},A_{(k-b+L+1)} B(now+1),A(L+1),A(k−b+L+1),根据前面,我们知道: B ( n o w + 1 ) = A ( k − b + L + 1 ) B_{(now+1)}=A_{(k-b+L+1)} B(now+1)=A(k−b+L+1),有根据next数组的定义,我们知道 A ( L + 1 ) ≠ A ( k − b + L + 1 ) A_{(L+1)}\ne A_{(k-b+L+1)} A(L+1)̸=A(k−b+L+1)(如果不是的话,L可以++),那么,我们可以知道 A ( L + 1 ) ≠ B ( n o w + 1 ) A_{(L+1)}\ne B_{(now+1)} A(L+1)̸=B(now+1),所以,这个时候 e x k = L ex_{k}=L exk=L。
- now>p
这也分两种情况:
- k>p
这个时候应当从 k k k开始暴力匹配,因为 k k k不在 p p p的范围内, k − b + 1 k-b+1 k−b+1也不在 p − b + 1 p-b+1 p−b+1的范围内,所以只能暴力匹配。
2.k≤p
首先,我们知道now>p,意味着什么?你真的学会的话,应该知道如果now>p,那么 k − b + 1 + L − 1 = k − b + L > ( p − b + 1 ) k-b+1+L-1=k-b+L>(p-b+1) k−b+1+L−1=k−b+L>(p−b+1)。
那么,这里面的 p − k + 1 p-k+1 p−k+1其实就是在 B 1 B_{1} B1至 B L B_{L} BL中与 B p − b + 1 B_{p-b+1} Bp−b+1所对应的位置,也就是与 A p A_{p} Ap所对应的位置。
那么我们就知道了三个关键位置 A p , B p − k + 1 , B p − b + 1 A_{p},B_{p-k+1},B_{p-b+1} Ap