FFT在字符串匹配中的应用

本文探讨了如何使用优化的乘积分解解决字符串匹配问题,包括标准匹配和带通配符的情况,通过C函数定义和减法卷积实现O(Knlogn)的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于一类字符串匹配问题:

给定长度分别为 m , n m,n m,n 的字符串 A , B A,B A,B,给出两个相同长度的字符串匹配的定义,要求找出 A A A B B B 中所有匹配的位置。

可能能用如下方式解决:

定义匹配函数 C ( a , b ) C(a,b) C(a,b),使得完全匹配函数 P ( i ) = ∑ j = 0 m − 1 C ( A j , B i + j ) P(i)=\sum_{j=0}^{m-1}C(A_j,B_{i+j}) P(i)=j=0m1C(Aj,Bi+j) 等于 0 0 0 当且仅当 A A A B [ i . . i + m − 1 ] B[i..i+m-1] B[i..i+m1] 匹配。

然后,我们将 C ( a , b ) C(a,b) C(a,b) 拆成若干个有关 a , b a,b a,b 的乘积,即 C ( a , b ) = ∑ k = 1 K f k ( a ) g k ( b ) C(a,b)=\sum_{k=1}^K f_k(a)g_k(b) C(a,b)=k=1Kfk(a)gk(b)。然后我们对每个 k k k 计算它对 P ( i ) P(i) P(i) 的贡献,即计算 P k ( i ) = ∑ j = 0 m − 1 f k ( A j ) g k ( B i + j ) P_k(i)=\sum_{j=0}^{m-1}f_k(A_j)g_k(B_{i+j}) Pk(i)=j=0m1fk(Aj)gk(Bi+j)。这是减法卷积,可以优化至 O ( n log ⁡ n ) O(n\log n) O(nlogn)

总时间复杂度 O ( K n log ⁡ n ) O(Kn\log n) O(Knlogn),一般来说 K K K 是常数。

举几个例子吧:

  • 一般的字符串匹配问题。

    一个想法是设 C ( a , b ) = a − b C(a,b)=a-b C(a,b)=ab,但这只对单个字符生效,对 P ( i ) P(i) P(i) 是不一定生效的,比如 "ab" \texttt{"ab"} "ab" "ba" \texttt{"ba"} "ba"

    正确的做法应该是设 C ( a , b ) = ( a − b ) 2 C(a,b)=(a-b)^2 C(a,b)=(ab)2,这样两个字符串一旦出现某个位置不同, P ( i ) P(i) P(i) 就一定大于 0 0 0

  • 带通配符 # \texttt{\#} # 的字符串匹配问题。

    上一题的扩展,直接设 C ( a , b ) = [ a ≠ # ] [ b ≠ # ] ( a − b ) 2 C(a,b)=[a\neq \texttt{\#}][b\neq \texttt{\#}](a-b)^2 C(a,b)=[a=#][b=#](ab)2 即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值