这。。。好强啊\(QwQ\)


思路:卷积?\(FFT\)?

提交:\(5\)次

错因:一开始的预处理写错了(竟然只错了最后几个大点)闹得我以为\(FFT\)写挂了\(QwQ\)

题解:

对四种字符分开考虑:我们设\(a[char][i]\)表示在第一个串\(s\)中,对于\(char \in \{'A','C','G','T'\}\)来说\(i\)位置是否能模糊匹配,换言之,若\(s[i]==char\),则\(a[char][j]=1,j\in [i-k,i+k]\)。

而对于第二个串\(t\)不做特殊处理,直接\(b[char][i]=[t[i]==char]\)。

我们在不加优化时,计算答案是\(O(n^2)\)的

for(R i=0;i<=lens-lent;++i) for(R j=1;j<=lent;++j) if(a[char][i+j]&&b[char][j]) ++c[i];

最后需要统计\(tmp=\sum [t[i]==char]\),若\(c[i]==tmp\)表示对\(char\)匹配成功。

所以我们要做\(4\)遍,对于每一个字符都做一遍。

考虑优化\(O(n^2)\)的过程:我们发现把\(t\)和\(b\)倒过来的话,上面的枚举相当于是一个卷积。

于是我们可以\(FFT\)。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define R register int
using namespace std;
namespace Luitaryi {
template<class I> inline I g(I& x) { x=0;
register I f(1); register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
} const int N=524292; const double PI=acos(-1.0);
int n,m,anss,k,K=1,l,l1,l2,p[N],a[4][N],b[4][N],c[N];
char s[N];
bool ans[N];
struct complex { double x,y; complex() {}
complex(double _x,double _y) {x=_x,y=_y;}
complex operator + (const complex& that) {return complex(x+that.x,y+that.y);}
complex operator - (const complex& that) {return complex(x-that.x,y-that.y);}
complex operator * (const complex& that) {return complex(x*that.x-y*that.y,x*that.y+y*that.x);}
}f[N],h[N];
inline int cvt(const char& c) {
if(c=='A') return 0; if(c=='C') return 1;
if(c=='G') return 2; if(c=='T') return 3;
}
inline void fft(complex* a,short op) {
for(R i=0;i<K;++i) if(i<p[i]) swap(a[i],a[p[i]]);
for(R l=1;l<K;l<<=1) { register complex w1(cos(PI/l),op*sin(PI/l));
for(R len=l<<1,i=0;i<K;i+=len) { register complex wn(1,0);
for(R j=0;j<l;++j,wn=wn*w1) { register complex x=a[i+j],y=a[i+j+l]*wn;
a[i+j]=x+y,a[i+j+l]=x-y;
}
}
} if(op==-1) for(R i=0;i<=n;++i) a[i].x=1.0*fabs(a[i].x)/K;
}
inline void main() {
g(l1),g(l2),g(k); scanf("%s",s);
for(R i=0;i<l1;++i) {
R tmp=cvt(s[i]); a[tmp][i]=1;
for(R j=i+1,lim=min(l1-1,i+k);j<=lim&&s[i]!=s[j];++j) a[tmp][j]=1;
for(R j=i-1,lim=max(0,i-k);j>=lim&&!a[tmp][j];--j) a[tmp][j]=1;
} scanf("%s",s); for(R i=0;i<l2;++i) b[cvt(s[i])][l2-i-1]=1;
n=l1+l2; while(K<=n) K<<=1,++l;
for(R i=0;i<K;++i) p[i]=(p[i>>1]>>1)|((i&1)<<(l-1));
for(R i=l2-1;i<=n-2;++i) ans[i]=1;
for(R i=0;i<4;++i) {
memset(f,0,sizeof(complex)*(K+2)),memset(h,0,sizeof(complex)*(K+2));
for(R j=0;j<l1;++j) f[j]=complex(a[i][j],0.0);
for(R j=0;j<l2;++j) h[j]=complex(b[i][j],0.0);
fft(f,1),fft(h,1); for(R i=0;i<=K;++i) f[i]=f[i]*h[i];
fft(f,-1); for(R i=0;i<=n-2;++i) c[i]=(int)(f[i].x+0.5);
R tmp=0; for(R j=0;j<l2;++j) tmp+=b[i][j];
for(R j=l2-1;j<=n-2;++j) ans[j]&=(tmp==c[j]);
} for(R i=l2-1;i<=n-2;++i) anss+=ans[i]; printf("%d\n",anss);
}
} signed main() {Luitaryi::main(); return 0;}

2019.08.12

88

51nod 1565 模糊搜索 FFT的更多相关文章

  1. 51nod 1565模糊搜索(FFT)

    题目大意就是字符串匹配,不过有一个门限k而已 之前有提到过fft做字符串匹配,这里和之前那种有些许不同 因为只有A,C,G,T四种字符,所以就考虑构造4个01序列 例如,模板串a关于'A'的01序列中 ...

  2. 51NOD 1565:模糊搜索——题解

    http://www.51nod.com/onlineJudge/questionCode.html#problemId=1565&noticeId=445588 有两个基因串S和T,他们只包 ...

  3. 【51nod】1565 模糊搜索

    题解 这个字符集很小,我们可以把每个字符拿出来做一次匹配,把第一个字符串处理每个出现过的该字符处理成一个区间加,即最后变成第一个字符串的该位置能够匹配某字符 例如对于样例 10 4 1 AGCAATT ...

  4. 51nod 算法马拉松 34 Problem D 区间求和2 (FFT加速卷积)

    题目链接  51nod 算法马拉松 34  Problem D 在这个题中$2$这个质数比较特殊,所以我们先特判$2$的情况,然后仅考虑大于等于$3$的奇数即可. 首先考虑任意一个点对$(i, j)$ ...

  5. FFT/NTT [51Nod 1028] 大数乘法 V2

    题目链接:51Nod 传送门 没压位,效率会低一点 1.FFT #include <cstdio> #include <cstring> #include <algori ...

  6. 51NOD 1258 序列求和 V4 [任意模数fft 多项式求逆元 伯努利数]

    1258 序列求和 V4 题意:求\(S_m(n) = \sum_{i=1}^n i^m \mod 10^9+7\),多组数据,\(T \le 500, n \le 10^{18}, k \le 50 ...

  7. 51nod 1172 Partial Sums V2 卡精度的任意模数FFT

    卡精度的任意模数fft模板题……这道题随便写个表就能看出规律来(或者说考虑一下实际意义),反正拿到这题之后,很快就会发现他是任意模数fft模板题.然后我就去网上抄了一下板子……我打的是最土的任意模数f ...

  8. 51nod 1028 大数乘法 V2 【FFT模板题】

    题目链接 模板题.. #include<bits/stdc++.h> using namespace std; typedef int LL; typedef double db; nam ...

  9. 51Nod 快速傅里叶变换题集选刷

    打开51Nod全部问题页面,在右边题目分类中找到快速傅里叶变换,然后按分值排序,就是本文的题目顺序. 1.大数乘法问题 这个……板子就算了吧. 2.美妙的序列问题 长度为n的排列,且满足从中间任意位置 ...

随机推荐

  1. 使用TypeScript创建Vue项目

    Vue的灵活性总是让代码看起来非常洗练,对TypeScript来说也是一种挑战, 好在Vue对TypeScript进行了一次全方位的适配. 相对于React严谨的代码,Redux啰嗦的样板代码,Vue ...

  2. (二)Spring Boot 官网文档学习之入门

    文章目录 Spring Boot 是什么 系统要求 Servlet 容器 Maven方式安装Spring Boot 编写第一个 Spring Boot 项目 原文:https://docs.sprin ...

  3. CF731E Funny Game

    题目描述 一个长度为 N 的序列 ai ,双方轮流操作 每次的操作是选择一个长度大于 1 的前缀,计算它的和 s ,然后 用 s 替换它的前缀,同时当前玩家获得 s 的分数. 当只剩下一个元素,游戏结 ...

  4. Python21之内嵌函数和闭包

    一.内嵌函数 内嵌函数指的是在一个函数体内部定义的函数,可以称它为函数的函数,也就是子函数,外部的函数称之为母函数,就类似局部变量和全局变量 子函数体内定义的变量只在其函数内部有效,但其内部可以调用母 ...

  5. vector 使用pair对

    pair是一种序偶结构<x,y> 如果我们希望使用pair但又不需要map对其排序,可以在vector中使用pair对 插入pair对使用make_pair<typename,typ ...

  6. Singer House CodeForces - 830D (组合计数,dp)

    大意: 一个$k$层完全二叉树, 每个节点向它祖先连边, 就得到一个$k$房子, 求$k$房子的所有简单路径数. $DP$好题. 首先设$dp_{i,j}$表示$i$房子, 分出$j$条简单路径的方案 ...

  7. Aop 打印参数日志时,出现参数序列化异常。It is illegal to call this method if the current request is not in asynchron

    错误信息: nested exception is java.lang.IllegalStateException: It is illegal to call this method if the ...

  8. WebUploader 上传图片回显

    /* fileMaxCount 最大文件数 buttonText 按钮文本 multiple 是否多选 */ (function ($) { $.fn.extend({ uploadImg: func ...

  9. Asp.net Report动态生成

    rdlc报表实质上是一个xml文件,如果要实现动态报表,就需要动态生成rdlc文件,实质上就是读写xml文件: protected XmlDocument GenerationAddReportCol ...

  10. 本地安装SQL Server 2017 Express和Microsoft SQL Server Management Studio 18.1

    sqlserver下载链接:https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 这个安装的是免费版的Express,当然也可 ...