「学习笔记」FFT x 字符串匹配

「学习笔记」FFT x 字符串匹配

设匹配函数 C(x,y) 为字符 x 和字符 y 匹配的值,是我们自己定义的值。

两个字符串匹配的值就是对应位置上的字符匹配的值的和。

对于文本串 S 和模式串 T,现在要求出 TS 中所有匹配的位置。

为了化成卷积的形式,把 T 反转。

这样 TSi 为结尾的子串的匹配值为:

j=0|T|1C(Sij,Tj)

为了能够区分不同位置的匹配值,定义生成函数:P(x)[xi] 代表 TSi 结尾的子串的匹配值。

那么:

P(x)=i=|T|1|S|xij=0|T|1C(Sij,Tj)

为了能通过观察匹配值来确定两个字符串,构造匹配函数 C(x,y)=(xy)2(字符的权值需满足两两不同,可以使用 ASCII 码来作为权值),则两个字符串匹配当且仅当匹配值为 0

那么:

P(x)=i=|T|1|S|xij=0|T|1(SijTj)2=i=|T|1|S|xij=0|T|1Sij2+Tj22SijTj=i=|T|1|S|xij=0|T|1Sij2+i=|T|1|S|xij=0|T|1Tj22i=|T|1|S|j=0|T|1SijxijTjxj

另外,为了使得边界满足卷积的形式,对于"溢出"的部分定义其权值为 0,也就是我们需要计算:

i=|T|1|S|xij=0|T|1Sij2+i=|T|1|S|xij=0|T|1Tj22i=|T|1|S|j=0iSijxijTjxj

前两个柿子可以预处理前缀和来做到线性求出,后面是个卷积的形式,可以通过 FFT O(nlogn) 求出。

所以就可以 O(nlogn) 做到字符串匹配了。

栗题一 luoguP4173

带通配符的字符串匹配。

尝试构造匹配函数 C(x,y) 满足:

  • xy 为通配符时值为 0

  • xy 都不为通配符,且相同时值为 0

  • xy 都不为通配符,且不相同时值 >0

设通配符的权值为 0C(x,y)=(xy)2xy

P(x)=i=|T|1|S|xij=0|T|1(SijTj)2SijTj=S3T2×S2T2+ST3

(这里的次方是点乘, 为卷积)

三次卷积,时间复杂度 O(nlogn)

栗题二 Codeforces 528 D

分别仅考虑 A,C,G,T,把匹配成功的位置取个交集就可以。

现在仅考虑 A,把 S 中不会和 A 匹配上的位置上的字符设为 o,把 T 中不是 A 的字符设为 #,则匹配函数 C(x,y) (其中 x 来自 Sy 来自 T)要满足:

  • =0,x=A,y=A
  • =0,x=A,y=#
  • >0,x=o,y=A
  • =0,x=o,y=#

这样的 C 才能满足匹配成功值为 0,否则大于 0

设:

  • S 中的 A 值为 0o 值为 1

  • T 中的 A 值为 1# 值为 0

  • C(x,y)=xy

对于每个字符只需要一次 FFT 就可以了。

Code

posted @   do_while_true  阅读(186)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?

This blog has running: 1845 days 1 hours 34 minutes 0 seconds

点击右上角即可分享
微信分享提示