现在我们拥有一个文本串B一个模式串A,询问A在B中出现的次数
很显然这是一个KMP的裸题,但是现在不考虑使用KMP,使用FFT来找A在B中出现的次数
首先定义函数
P ( x ) = ∑ i = 0 m − 1 ( A ( i ) − B ( x − m + i + 1 ) ) P(x)=\sum_{i=0}^{m-1}(A(i)-B(x-m+i+1)) P(x)=i=0∑m−1(A(i)−B(x−m+i+1))
这个函数代表,字符串A在B中匹配以x为最终位置的时候的价值,我们可以看到如果m个字符都匹配上了,那么 P ( x ) = 0 P(x)=0 P(x)=0,因此我们需要快速求出 P ( x ) P(x) P(x),我们做一下化简
P ( x ) = ∑ i = 0 m − 1 ( A ( i ) − B ( x − m + i + 1 ) ) 2 = ∑ i = 0 m − 1 ( A 2 ( i ) + B 2 ( x − m + i + 1 ) − A ( i ) ∗ B ( x − m + i + 1 ) ) = ∑ i = 0 m − 1 A 2 ( i ) + ∑ i = 0 m − 1 B 2 ( x − m + i + 1 ) − ∑ i = 0 m − 1 A ( i ) ∗ B ( x − m + i + 1 ) P(x)=\sum_{i=0}^{m-1}(A(i)-B(x-m+i+1))^2 \\ = \sum_{i=0}^{m-1}(A^2(i)+B^2(x-m+i+1) - A(i) * B(x-m+i+1)) \\ =\sum_{i=0}^{m-1}A^2(i)+\sum_{i=0}^{m-1}B^2(x-m+i+1) - \sum_{i=0}^{m-1}A(i) * B(x-m+i+1) P(x)=i=0∑m−1(A(i)−B(x−m+i+1))2=i=0∑m−1(A2(i)+B2(x−m+i+1)−A(i)∗B(x−m+i+1))=i=0∑m−1A2(i)+i=0∑m−1B2(x−m+i+1)−i=0∑m−1A(i)∗B(x−m+i+1)
前面两项很明显就是前缀和处理即可,但是对于最后的一项,我们要给他转化成卷积的形式,这样才可以方便使用FFT去求解,我们不妨考虑将字符串A逆转,得到字符串S,再将S替换掉公式中的A得到‘
P ( x ) = ∑ i = 0 m − 1 S 2 ( m − i − 1 ) + ∑ i = 0 m − 1 B 2 ( x − m + i + 1 ) − ∑ i = 0 m − 1 S ( m − i − 1 ) ∗ B ( x − m + i + 1 ) P(x)=\sum_{i=0}^{m-1}S^2(m-i-1)+\sum_{i=0}^{m-1}B^2(x-m+i+1) - \sum_{i=0}^{m-1}S(m-i-1) * B(x-m+i+1) P(x)=i=0∑m−1S2(m−i