ACM算法总结 字符串(三)




带通配符的单模式匹配

平常的单模式匹配就是给出一个模式串 t,给出一个文本串 s,问 s 中能够在哪些位点完全匹配 t,这个用 KMP 可以很好地解决。但是如果在模式串和文本串中有一些通配符,也就是这些符号匹配什么都可以,那这样就解决不了了。比如说 t=a*bs=aebr*ob,其中 * 表示通配符,那么 t 在 s 中可以匹配的位点为 1 5(下标从 1 开始)。

解决办法本质上是把匹配转变为一个数学公式 G(x),表示模式串在原串的 x 处的匹配公式,并且这个 G(x) 满足 x 0 , G ( x ) 0 \forall x\ge 0,G(x)\ge 0 ,且当 G(x)=0 时表示可以匹配。一般 G(x) 由一些子公式组成。

对于带通配符的单模式匹配问题,我们可以设子函数 p(a, b) 表示 t[a] 和 s[b] 的匹配函数,p(a, b) 和 G 具有一样的性质,所以我们的主要目标就是如何构造函数 p,使得它满足这个性质。比如对于这个问题,我们可以把 * 设为0,然后设 p ( a , b ) = ( t [ a ] s [ b ] ) 2 t [ a ] s [ b ] p(a,b)=(t[a]-s[b])^2t[a]s[b] ,那么满足 p ( a , b ) 0 p(a,b)\ge0 ,并且仅当 t[a]=s[b] 或两个中有通配符时才成立 p(a, b)=0 ,其余情况都大于 0 。所以有 G ( x ) = i = 0 m 1 p ( i , x + i ) G(x)=\sum\limits_{i=0}^{m-1}p(i,x+i) ,可以证明这个 G(x) 满足上面的限制。

进一步,我们把模式串 t 翻转(这是为了凑出常数),然后公式就变为 G ( x ) = i = 0 m 1 p ( m i 1 , x + i ) G(x)=\sum\limits_{i=0}^{m-1}p(m-i-1,x+i) ,发现 m i 1 + x + i = m 1 + x m-i-1+x+i=m-1+x ,对于特定的 x 是一个常数,那把 p 带入展开之后,这不就是一个很长的卷积和式么。用几次 FFT 加速,就可以算出所有的 G(x),然后一一判断是否等于 0 来决定是否匹配。

其实一般的单模式匹配也可以这么做,只要改一下 p 函数,改成 p ( a , b ) = ( t [ a ] s [ b ] ) 2 p(a,b)=(t[a]-s[b])^2 就可以了。

猜你喜欢

转载自blog.csdn.net/dragonylee/article/details/106460636