字符串匹配进阶

Posted XINNNNNNNYU

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符串匹配进阶相关的知识,希望对你有一定的参考价值。

FFT

A位模式串,长度为n;B为文本串,长度为m。

1.没有通配符的

  • 首先引入一个匹配函数 C ( x , y ) = A ( x ) − B ( y ) C(x,y) = A(x) - B(y) C(x,y)=A(x)B(y),当C(x,y) = 0,我们认为A的第x字符和B的第y个字符相等。
  • 再将一个字符匹配扩展到一个字符串。
  • 那么,完全匹配函数 P ( x ) = ∑ i = 0 m − 1 C ( i , x − m + i + 1 ) P(x) =\\displaystyle \\sum^m-1_i=0 C(i,x-m+i+1) P(x)=i=0m1C(i,xm+i+1) ,若P(x) = 0,则B以x结尾的连续m位子串和A完全匹配。
  • 上面的完全匹配函数存在一些错误
    • 把求和函数拆开会发现就是匹配的两个串的每个字符分别相加,然后;两个和相减。那么只要字符的类型,个数对应相同就被判定相同,忽略了每个字符的对应关系。
    • 产生错误的原因是每个字符的匹配函数有正有负,求和可能相互抵消为0。
    • 解决方法就是把匹配函数 C ( x , y ) C(x,y) C(x,y)平方,因为若干个平方数相加=0只能是每一项都为0,和我们完全匹配时每个位置的 C ( x , y ) = 0 C(x,y)=0 C(x,y)=0时等价的。
    • 等价转化—— 我们把A反转变成S,那么A(i) = S(m-i-1)。因为这样子匹配函数的x,y相加总是等于一个常数。(这很重要)
  • 正确的完全匹配函数为 P ( x ) = ∑ i = 0 m − 1 ( S [ m − i − 1 ] − B [ x − m + i + 1 ] ) 2 P(x) =\\displaystyle \\sum^m-1_i=0 (S[m-i-1] - B[x-m+i+1])^2 P(x)=i=0m1(S[mi1]B[xm+i+1])2
  • 将函数暴力展开为 P ( x ) = ∑ i = 0 m − 1 ( S [ m − i − 1 ] 2 + B [ x − m + i + 1 ] 2 − 2 S [ m − i − 1 ] B [ x − m + i + 1 ] ) P(x) =\\displaystyle \\sum^m-1_i=0 (S[m-i-1]^2 + B[x-m+i+1]^2 - 2 S[m-i-1] B[x-m+i+1]) P(x)=i=0m1(S[mi1]2+B[xm+i+1]22S[mi1]B[xm+i+1])
  • 再展开为三部分
    1. ∑ i = 0 m − 1 S [ m − i − 1 ] 2 \\displaystyle \\sum^m-1_i=0 S[m-i-1]^2 i=0m1S[mi1]2 显然,这是个定值记作T,我们可以 O ( m ) O(m) O(m)暴力预处理
    2. ∑ i = 0 m − 1 B [ x − m + i + 1 ] 2 \\displaystyle \\sum^m-1_i=0B[x-m+i+1]^2 i=0m1B[xm+i+1]2 这是一个长度为m的区间和,我们通过预处理前缀和数组f ( x ),然后 O ( 1 ) O(1) O(1)得到
    3. − 2 ∑ i = 0 m − 1 S [ m − i − 1 ] B [ x − m + i + 1 ] \\displaystyle -2\\sum^m-1_i=0S[m-i-1] B[x-m+i+1] 2i=0m1S[mi1]B[xm+i+1] 通过上面我们把A用他的反转S替换后,我们发现(m-i-1)+(x-m+i+1) 恒等于x。那么公式为 − 2 ∑ i + i = x S [ i ] B [ j ] \\displaystyle -2\\sum_i+i=xS[i] B[j] 2i+i=xS[i]B[j]
      • g ( x ) = ∑ i + i = x S [ i ] B [ j ] \\displaystyle g(x) = \\sum_i+i=xS[i] B[j] g(x)=i+i=xS[i]B[j] ,显然这是个多项式乘法,可以通过FFT求出所有值
  • P ( x ) = T + f ( x ) − f ( x − m ) − 2 g ( x ) P(x) = T + f(x) - f(x-m) -2g(x) P(x)=T+f(x)f(xm)2g(x) ,每个函数都可以通过上述求出,再 O ( n ) O(n) O(n)求出所有P(x)
  1. 有通配符的
  • 调整匹配函数——和上述没有通配符的相同,但是我们要去掉通配符位置的贡献。

  • 将原字符串是通配符的值设为0,再修改完全匹配匹配函数为 P ( x ) = ∑ i = 0 m − 1 ( S [ m − i − 1 ] − B [ x − m + i + 1 ] ) 2 S [ m − i − 1 ] B [ x − m + i + 1 ] P(x) =\\displaystyle \\sum^m-1_i=0 (S[m-i-1] - B[x-m+i+1])^2S[m-i-1]B[x-m+i+1] P(x)=i=0m1(S[mi1]B[xm+i+1])2S[mi1]B[xm+i+1]

    其中一个为通配符就会乘上0,最后贡献为0

  • 暴力展开-> P ( x ) = ∑ i = 0 m − 1 ( S [ m − i − 1 ] 3 B [ x − m + i + 1 ] + B [ x − m + i + 1 ] 3 S [ m − i − 1 ] − 2 ( S [ m − i − 1 ] B [ x − m + i + 1 ] ) 2 ) P(x) =\\displaystyle \\sum^m-1_i=0 (S[m-i-1]^3B[x-m+i+1] + B[x-m+i+1]^3S[m-i-1] - 2 (S[m-i-1] B[x-m+i+1])^2) P(x)=i=0m1(S[mi1]3B[xm+i+1]+B[xm+i+1]3S[mi1]2(S[mi1]B[xUva 11468 改良版AC自动机

    AC自动机

    Poj 1961 KMP

    什么是KMP算法?KMP算法推导

    Trie图 模板

    KMP算法的next[]数组通俗解释