题目大意就是字符串匹配,不过有一个门限k而已

之前有提到过fft做字符串匹配,这里和之前那种有些许不同

因为只有A,C,G,T四种字符,所以就考虑构造4个01序列

例如,模板串a关于'A'的01序列中,1代表这个位置可以匹配,而0则代表不能匹配。

这样构造出4个序列后,再对匹配串b做同样的处理

下面用a['A']代表a关于'A'的01序列,b同理

然后可以知道a['A'][i]&b['A'][i]如果是1则代表可以匹配,如果是0则代表不能匹配。

那么在位置i两个串能否匹配就可以写做

for(x = i ~ i+lenb) ans += a['A'][i]&b['A'][i]

如果ans恰好等于b中'A'的个数,那么就说明'A'匹配成功,接下来做'C','G','T'的情况

如果都可以匹配成功,那么这个位置就可以匹配了

如何用fft做这个呢?实际上也很简单

把b串颠倒一下就变成了a['A'][i]&b['A'][lenb-i]

就是一个卷积形式,于是就可以fft了

(测试感觉stl里的complex比较慢,非递归比递归快很多)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <bitset>
#include <cmath>
#include <complex>
using namespace std;
const double pi = acos(-);
const int maxn = ;
int A[][maxn], B[][maxn], ANS[maxn];
struct cp {
double a,b;
cp() { a = b = ; }
cp(double _a, double _b):a(_a), b(_b) {}
cp operator+(const cp&y)const { return cp(a+y.a, b+y.b); }
cp operator-(const cp&y)const { return cp(a-y.a, b-y.b); }
cp operator*(const cp&y)const { return cp(a*y.a-b*y.b,a*y.b+b*y.a); }
cp operator!()const { return cp(a,-b); }
};
int T[];
int la, lb, k;
char str[maxn];
class FFT {
int n, L, R[maxn];
cp a[maxn], b[maxn];
void DFT(cp *a,int n,int f) {
for(int i = ; i < n; i++) if(i < R[i]) swap(a[i], a[R[i]]);
for(int i = ; i < n; i <<= ) {
cp t, x, wn(cos(pi/i), sin(pi*f/i));
for(int j = ; j < n; j += (i<<)) {
cp w(, );
for(int k = ; k < i; k++,w = w*wn) {
x = a[j+k];
t = w*a[j+k+i];
a[j+k] = x+t;
a[j+k+i] = x-t;
}
}
}
}
public:
int c[maxn];
FFT() { memset(R, , sizeof(R)); }
void init(int *A, int *B, int n1, int n2) {
memset(a, , sizeof(a));
memset(b, , sizeof(b));
for(int i = ; i <= n1; i++) a[i] = cp(A[i], );
for(int i = ; i <= n2; i++) b[i] = cp(B[i], );
n2 += n1;
for(n = , L = ; n <= n2; n <<= ) L++;
for(int i = ; i < n; i++) R[i] = (R[i>>]>>)|((i&)<<(L-));
}
void calc() {
DFT(a, n, );
DFT(b, n, );
for(int i = ; i <= n; i++) a[i] = a[i]*b[i];
DFT(a, n, -);
for(int i = ; i <= n; i++) c[i] = (a[i].a/n + 0.5);
}
} fft; int main() {
cin>>la>>lb>>k;
T['A'] = ; T['C'] = ; T['G'] = ; T['T'] = ;
scanf("%s", str);
for(int i = ; i < la; i++) {
int ty = T[str[i]];
A[ty][i] = ;
for(int j = i+; j <= min(i+k, la-); j++) {
if(ty == T[str[j]]) break;
A[ty][j] = ;
}
for(int j = i-; j >= max(, i-k); j--) {
if(A[ty][j]) break;
A[ty][j] = ;
}
}
scanf("%s", str);
for(int i = ; i < lb; i++) {
int ty = T[str[i]];
B[ty][lb-i-] = ;
}
for(int i = lb-; i <= la+lb-; i++) ANS[i] = ;
for(int i = ; i < ; i++) {
fft.init(A[i], B[i], la, lb);
fft.calc();
int t = ;
for(int j = ; j < lb; j++) if(B[i][j]) t++;
for(int j = lb-; j <= la+lb-; j++)
ANS[j] &= (fft.c[j] == t);
}
int ans = ;
for(int i = lb-; i <= la+lb-; i++) ans += ANS[i];
cout<<ans<<endl;
}

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

  1. 51nod 1565 模糊搜索 FFT

    这...好强啊\(QwQ\) 思路:卷积?\(FFT\)? 提交:\(5\)次 错因:一开始的预处理写错了(竟然只错了最后几个大点)闹得我以为\(FFT\)写挂了\(QwQ\) 题解: 对四种字符分开 ...

  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. 【路由和交换之H3C自导自演】

    H3C配置自导自演 显示和维护及恢复 1:display display history-command    :查看历史命令记录 display diagnostic-information :查看 ...

  2. 为何企业钟爱H5响应式网站? html5响应式网站的优势与特点

    随着移动互联网时代的到来,H5响应式网站应运而生,并成功获得了商家.访客.搜索引擎等的青睐!越来越多的企业也选择了H5响应式建站,可为何企业钟爱H5响应式网站呢?难道传统网站不好吗?这个不能妄下结论, ...

  3. 8-C++远征之继承篇-学习笔记

    C++远征之继承篇 开篇介绍 整个C++远征计划: 起航->离港->封装->继承 为什么要用继承? 为什么要有继承? 如何来定义基类 <----> 派生类? 基类到派生类 ...

  4. node session会话

    会话机制: 浏览器-->服务器 浏览器<--服务器 (产生一个会话id,保存在cookie中) 浏览器-->服务器(服务器根据会话id关联到相应数据信息体data) var expr ...

  5. Hbase数据IO

    场景及方案分析 场景1:logs --> HBase logs -> flume -> hfile -> import -> HBase (实时) csv导入HBase ...

  6. 【多线程】 Task ,async ,await

    [多线程]Task ,async ,await 一. WinForm 里经常会用到多线程, 多线程的好出就不多说了,来说说多线程比较麻烦的地方 1. UI 线程与其他线程的同步,主要是 Form 和 ...

  7. 云计算之路-阿里云上:奇怪的CPU 100%问题

    这篇博文记录一下6月1日在阿里云上遇到的奇怪的CPU 100%问题,希望多年以后能真相大白. 那天负载均衡(SLB)中只放了1台云服务器(平时都放2台),由于是节假日,虽然只放了一台,但这台服务器的负 ...

  8. 面向对象 公有私有 property classmethod staticmethod

    接口类(抽象类)--------就是一种规范 面向对象的私有与公有 对于每一个类的成员而言都有两种形式: 公有成员,在任何地方都能访问 私有成员,只有在类的内部才能方法 私有成员和公有成员的访问限制不 ...

  9. PostgreSQL基本配置

    记一下Postgresql的基本操作,在Ubuntu下使用apt-get安装是不会像MySQL那样都配置好了,而是要安装后再配置: 1. 基本安装 # 安装postgresql和pgadmin(一个管 ...

  10. 常见 SQL语句使用 增删改查

    一.常见的增删改查(一).查:1.SELECT 列名称 FROM 表名称,其中列名可以是多个,中间用豆号分开,如SELECT LastName,FirstName FROM Persons: 2.SE ...