本文半原创

参考资料:其实就是照抄的什么参考啊

我们知道KMP可以用来在线性复杂度内进行制胡窜匹配

今天教您一种新方法:用FFT进行字符串匹配

您可能觉得这很玄学,FFT不是做多项式卷积的吗,怎么还可以做制胡窜匹配

您先别着急,请接着听

我们设两个字符串--模式串\(a\),长度为\(m\),文本串\(b\),长度为\(n\)。设下标为从0开始

定义函数\(a(i)\)返回a串位置i的字符,\(b(i)\)返回b串位置i的字符(其实就是下标)

定义匹配函数\(c(x,y)=a(x)-b(y)\),代表a串x位置和b串y位置是否匹配(也就是是否相同)

如果匹配,那么\(c(x,y)=0\)对吧

然后我们再定义完全匹配函数\(\displaystyle P(x)=\sum_{i=0}^{m-1}c(i,x-m+i+1)\),若\(P(x)=0\),则称B以第\(x\)位结束的连续\(m\)位与A完全匹配

但是这个匹配函数是有问题的

他会导致字符串"ab"和字符串"ba"匹配,你想想是不是,一个-1一个1,加起来就是0喽

所以我们稍微改一下匹配函数:\(c(x,y)=(a(x)-b(y))^2\),保证\(c(x,y)\ge 0\),这样是不是就没问题了啊

所以我们的\(\displaystyle P(x)=\sum_{i=0}^{m-1}(a(i)-b(x-m+i+1))^2\)

您还没有看出什么玄机来

我们可以把\(a\)串翻转,设翻转后的串为\(s\),则满足\(a(i)=s(m-i-1)\)对吧,下标是从0开始的

所以我们的\(\displaystyle P(x)=\sum_{i=0}^{m-1}(s(m-i-1)-b(x-m+i+1))^2\)

继续观察!发现什么了???要不我们换一下元,用\(i\)替换\(m-i+1\),注意其中\(i\)的范围由\([0,m-1]\)变换到了\([0,m-1]\)你直接说没有变不就得了

所以我们的\(\displaystyle P(x)=\sum_{i=0}^{m-1}(s(i)-b(x-i))^2\)

要不我们把完全平方展开下

所以我们的\(\displaystyle P(x)=\sum_{i=0}^{m-1}(s^2(i)-2s(i)b(x-i)+b^2(x-i))\)

拆一下sigma

所以我们的\(\displaystyle P(x)=\sum_{i=0}^{m-1}s^2(i)+\sum_{i=0}^{m-1}b^2(x-i)-2\sum_{i=0}^{m-1}s(i)b(x-i)\)

这式子是不是不错啊

第一项是个定值,可以直接算出啦

第二项,由于加的是一段区间,可以O(n)预处理前缀和

第三项!!!这是什么?不就是我们的卷积吗

FFT即可

时间复杂度O(nlogn)

诶对了

到了这里您可能会发现这个时间复杂度都没KMP优秀

您可能会问我这个算法有个吊毛用啊,FFT还没KMP好写(FFT其实也挺好写的)

别急听我接着讲

如果我们的字符串里有通配符呢

就是说这个通配符跟什么字符匹配都行(注意是字符而不是字符串)

您会发现KMP就GG了

然后我们继续考虑FFT做法

这次我们强制令通配符的ascii为0

定义我们的匹配函数\(c(x,y)=(a(x)-b(y))^2a(x)b(y)\),那么是不是对于有通配符的都能保证\(c=0\)了呢

然后就是推一波式子的事情了

大家可以试着推推

行了下面是结果

所以我们的\(\displaystyle P(x)=\sum_{i=0}^{m-1}(s^3(i)b(x-i)-2s^2(i)b^2(x-i)+s(i)b^3(x-i))\)

我们对\(s,s^2,s^3,b,b^2,b^3\)进行FFT,然后再DFT回来就行啦

例题

有了这个算法之后不就是板子题啦

例题

这题可以用SAM做,@顾z

好像还可以用哈希做。。。还是@顾z

温馨提示:根据生物学知识,人类DNA上的碱基只有四种

大家可以想一想正解

我们对ATCG贡献分开算,这里的贡献指的是不匹配的字符数

假设我们当前强行只计算模式串中A对于匹配串的贡献

先把模式串翻转一下

那么我们把模式串的A当做1,T C G都当做0,把文本串的A当做0,T C G都当做1

然后直接让模式串和文本串卷积(数字很小,可以用NTT优化卷积)

累加的贡献就是A与TCG不匹配的

最后把所有<=3的位置统计即为答案

总结:

这种带通配符/不匹配的字符串题我们一般是构造关于字符串的函数,对某个字符串翻转,然后进行卷积再各种处理。

这种题只是FFT的一种应用。

FFT字符串匹配的更多相关文章

  1. P4173 残缺的字符串(FFT字符串匹配)

    P4173 残缺的字符串(FFT字符串匹配) P4173 解题思路: 经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1 ...

  2. BZOJ4259: 残缺的字符串(FFT 字符串匹配)

    题意 题目链接 Sol 知道FFT能做字符串匹配的话这就是个裸题了吧.. 考虑把B翻转过来,如果\(\sum_{k = 0}^M (B_{i - k} - A_k)^2 * B_{i-k}*A_k = ...

  3. 2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 H题 Rock Paper Scissors Lizard Spock.(FFT字符串匹配)

    2018 ACM-ICPC 中国大学生程序设计竞赛线上赛:https://www.jisuanke.com/contest/1227 题目链接:https://nanti.jisuanke.com/t ...

  4. CF-528D Fuzzy Search(FFT字符串匹配)

    Fuzzy Search 题意: 给定一个模式串和目标串按下图方式匹配,错开位置不多于k 解题思路: 总共只有\(A C G T\)四个字符,那么我们可以按照各个字符进行匹配,比如按照\(A\)进行匹 ...

  5. CF528D Fuzzy Search 字符串匹配+FFT

    题意: DNA序列,在母串s中匹配模式串t,对于s中每个位置i,只要s[i-k]到s[i+k]中有c就认为匹配了c.求有多少个位置匹配了t. 分析: 这个字符串匹配的方式,什么kmp,各种自动机都不灵 ...

  6. BZOJ4259:残缺的字符串(FFT与字符串匹配)

    很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺. 你想对这两 ...

  7. Luogu P4173 残缺的字符串-FFT在字符串匹配中的应用

    P4173 残缺的字符串 FFT在字符串匹配中的应用. 能解决大概这种问题: 给定长度为\(m\)的A串,长度为\(n\)的B串.问A串在B串中的匹配数 我们设一个函数(下标从\(0\)开始) \(C ...

  8. 字符串匹配的KMP算法

    ~~~摘录 来源:阮一峰~~~ 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”? 许 ...

  9. {Reship}{KMP字符串匹配}

    关于KMP字符串匹配的介绍和归纳,作者的思路非常清晰,推荐看一下 http://blog.csdn.net/v_july_v/article/details/7041827

随机推荐

  1. CKEditor 自定义按钮插入服务端图片

    CKEditor 富文本编辑器很好用,功能很强大,在加上支持服务端图片上传的CKFinder更是方便, 最近在使用CKFinder的时候发现存在很多问题,比如上传图片的时候,图片不能按时间降序排列,另 ...

  2. Task用法(2)-任务等待wait

    1.Wait 用法   默认情况下,Task 是有线程池中的异步线程执行,是否执行完成,可以通过Task的的属性IsCompleted 来判断,  如果想在子线程工作完成之后,在进行后续主线程工作可以 ...

  3. react常见面试题

    当你调用 setState 的时候,发生了什么事? 当调用 setState 时,React会做的第一件事情是将传递给 setState 的对象合并到组件的当前状态.这将启动一个称为和解(reconc ...

  4. mybaits中date类型显示时分秒(orcle数据库)

    <insert id="insert" parameterType="daSysLoginLog"> insert into DA_SYS_LOGI ...

  5. day35 02-Hibernate持久化对象状态及状态转换

    hibernate内置有一个c3p0,不用引入c3p0的jar包也行. 现在其实可以不用去创建表和实体类.因为hibernate可以自动帮我们生成.只要把映射建好了它就可以自动帮我们生成. 创建实体类 ...

  6. POJ 1741 点分治

    方法:指针扫描数组 每次选择树的重心作为树根,从树根出发进行一次DFS,求出点到树根的距离,把节点按照与树根的的距离放进数组d,设置两个指针L,R分别从前.后开始扫描,每次满足条件时答案累加R-L., ...

  7. go语言的第一个helloworld

    1.新建一个hello.go文件 添加如下代码: package main  // 代码包声明语句. import "fmt" //系统包用来输出的 func main() { / ...

  8. String/StringBuilder 类 统计字符串中字符出现的次数

    1.1. 训练描述:[方法.String类] 一.需求说明:定义如下字符串: String str = “javajfiewjavajfiowfjavagkljjava”; 二.请分别定义方法统计出: ...

  9. Win10 VS2013 suitesparse-metis-for-windows 1.3.1

    suitesparse-metis-for-windows 1.3.1 安装包内附SuiteSparse 4.5.1, Metis 5.1.0和 lapack 3.4.1 Github上面由整理好的s ...

  10. Entity Framework Tutorial Basics(17):DBSet Class

    DBSet Class DBSet class represents an entity set that is used for create, read, update, and delete o ...