51nod 1565 模糊搜索 FFT
这。。。好强啊\(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的更多相关文章
- 51nod 1565模糊搜索(FFT)
题目大意就是字符串匹配,不过有一个门限k而已 之前有提到过fft做字符串匹配,这里和之前那种有些许不同 因为只有A,C,G,T四种字符,所以就考虑构造4个01序列 例如,模板串a关于'A'的01序列中 ...
- 51NOD 1565:模糊搜索——题解
http://www.51nod.com/onlineJudge/questionCode.html#problemId=1565¬iceId=445588 有两个基因串S和T,他们只包 ...
- 【51nod】1565 模糊搜索
题解 这个字符集很小,我们可以把每个字符拿出来做一次匹配,把第一个字符串处理每个出现过的该字符处理成一个区间加,即最后变成第一个字符串的该位置能够匹配某字符 例如对于样例 10 4 1 AGCAATT ...
- 51nod 算法马拉松 34 Problem D 区间求和2 (FFT加速卷积)
题目链接 51nod 算法马拉松 34 Problem D 在这个题中$2$这个质数比较特殊,所以我们先特判$2$的情况,然后仅考虑大于等于$3$的奇数即可. 首先考虑任意一个点对$(i, j)$ ...
- FFT/NTT [51Nod 1028] 大数乘法 V2
题目链接:51Nod 传送门 没压位,效率会低一点 1.FFT #include <cstdio> #include <cstring> #include <algori ...
- 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 ...
- 51nod 1172 Partial Sums V2 卡精度的任意模数FFT
卡精度的任意模数fft模板题……这道题随便写个表就能看出规律来(或者说考虑一下实际意义),反正拿到这题之后,很快就会发现他是任意模数fft模板题.然后我就去网上抄了一下板子……我打的是最土的任意模数f ...
- 51nod 1028 大数乘法 V2 【FFT模板题】
题目链接 模板题.. #include<bits/stdc++.h> using namespace std; typedef int LL; typedef double db; nam ...
- 51Nod 快速傅里叶变换题集选刷
打开51Nod全部问题页面,在右边题目分类中找到快速傅里叶变换,然后按分值排序,就是本文的题目顺序. 1.大数乘法问题 这个……板子就算了吧. 2.美妙的序列问题 长度为n的排列,且满足从中间任意位置 ...
随机推荐
- Tomcat报错:No result type specified for result named 'success'
今天学Struts, tomcat报出了异常信息 Exception starting filter [struts2] Unable to load configuration.还有 No resu ...
- Python06之分支和循环1(三目运算符)
Python 为了使得程序更加简洁而新引入过来的一个三目操作符,顾名思义就是有三个参数. 格式: x if 条件表达式 else y 先判断条件表达式真假,真则取 x 的值,否则取 y 的值. 例如: ...
- 剑指offer11:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。(进制转换,补码反码)
1. 题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 2. 思路和方法 使用移位(<<)和 “| & !”操作来实现.1的二进制是:前面都是0,最后一位 ...
- C#中使用XML存储数据
创建XML文档 首先引用System.Xml命名空间 1.初始化一个实例 XmlDocument xd = new XmlDocument(); 2.创建XML头文件声明 XmlDeclaration ...
- javascript 之 扩展对象 jQuery.extend
在JQuery的API手册中,extend方法挂载在JQuery 和 JQuery.fn两个不同的对象上,但在JQuery内部代码实现的是相同的,只是功能各不相同. 官方解释: jQuery.exte ...
- Jenkins 发邮件的Job
Jenkins要做到构建失败的时候发送邮件,常规做法是加个全局的post failure,类似这样的代码 pipeline { agent any stages { stage('deploy') { ...
- Saas软件更新以及小程序更新的教训
Saas软件即使版本更新多次,也要兼顾老客户,兼容旧功能. 对于小程序调用的接口,无法保证客户会更新小程序,因此需要兼容使用旧版本小程序的客户,更不能删除接口.
- 【转载】Sqlserver限制最大可使用内存
在Sqlserver的使用过程中,我们会发现随着运行时间的增长,Sqlserver占用的系统也越来越大,查了网上的相关资料说,Sqlserver在查询完相应数据后,为了下一次查询的性能,并不会马上释放 ...
- javascript中bind()、call()、apply()的使用
一直以来对bind().apply().call()这三个方法都模模糊糊的,现在有时间详细的看看这三个方法,并记录下来. bind() 参考文档:https://developer.mozilla.o ...
- FreeRTOS 基础简介
为什么选择FreeRTOS UCOS资料多,尤其是中文资料.FreeRTOS资料少,而且大多数是英文的.原因如下: 1.FreeRTOS免费!UCOS收费.这是主要原因 2.很多半导体厂商,采用Fre ...