题解

这个字符集很小,我们可以把每个字符拿出来做一次匹配,把第一个字符串处理每个出现过的该字符处理成一个区间加,即最后变成第一个字符串的该位置能够匹配某字符

例如对于样例

10 4 1

AGCAATTCAT

ACAT

我们做A的时候,把第一个串处理成

AAAAAA00AA0

第二个串

A0A0

那么就变成第二个串从第一个串每个位置开始能不能匹配上第二个串所有的A了

我们发现把第二个串反序之后和第一个串求一个卷积,那么第一个串每个位置如果系数等于第二个串该字符出现次数,那么证明这个位置可以匹配一个第二个串的末尾

对于每个位置把所有字符集的答案&起来就好

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#define enter putchar('\n')
#define space putchar(' ')
//#define ivorysi
#define pb push_back
#define MAXN 200005
#define pii pair<int,int>
#define mp make_pair
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 - '0' + c;
c = getchar();
}
res = res * f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
const db PI = acos(-1.0);
char s1[MAXN],s2[MAXN];
int K,S,T;
int a[MAXN],b[MAXN],c[MAXN];
bool vis[MAXN];
struct Complex {
db r,i;
Complex(db real = 0.0,db image = 0.0) {
r = real;i = image;
}
friend Complex operator + (const Complex &a,const Complex &b) {
return Complex(a.r + b.r,a.i + b.i);
}
friend Complex operator - (const Complex &a,const Complex &b) {
return Complex(a.r - b.r,a.i - b.i);
}
friend Complex operator * (const Complex &a,const Complex &b) {
return Complex(a.r * b.r - a.i * b.i,a.r * b.i + a.i * b.r);
}
}p1[MAXN * 4],p2[MAXN * 4];
void FFT(Complex *p,int L,int on) {
for(int i = 1 , j = L / 2 ; i < L - 1 ; ++i) {
if(i < j) swap(p[i],p[j]);
int k = L / 2;
while(j >= k) {
j -= k;
k >>= 1;
}
j += k;
}
for(int h = 2 ; h <= L ; h <<= 1) {
Complex wn = Complex(cos(on * 2 * PI / h),sin(on * 2 * PI / h));
for(int k = 0 ; k < L ; k += h) {
Complex w = Complex(1.0,0.0);
for(int j = k ; j < k + h / 2 ; ++j) {
Complex u = p[j],t = p[j + h / 2] * w;
p[j] = u + t;
p[j + h / 2] = u - t;
w = w * wn;
}
}
}
if(on == -1) {
for(int i = 0 ; i < L ; ++i) p[i].r /= L;
}
}
int ci(char c) {
if(c == 'A') return 1;
else if(c == 'G') return 2;
else if(c == 'C') return 3;
else return 4;
}
void Init() {
read(S);read(T);read(K);
scanf("%s%s",s1 + 1,s2 + 1);
for(int i = 1 ; i <= S ; ++i) a[i] = ci(s1[i]);
for(int i = 1 ; i <= T ; ++i) b[i] = ci(s2[i]);
}
void Solve() {
memset(vis,1,sizeof(vis));
for(int i = 1 ; i <= 4; ++i) {
int t = 1;
while(t <= S + T) t <<= 1;
int cnt = 0;
memset(c,0,sizeof(c));
for(int j = 1 ; j <= S ; ++j) {
if(a[j] == i) c[max(1,j - K)]++,c[min(j + K + 1,S + 1)]--;
}
for(int j = 1 ; j <= S ; ++j) {
c[j] += c[j - 1];
if(c[j]) p1[j - 1] = Complex(1.0,0.0);
else p1[j - 1] = Complex(0.0,0.0);
}
for(int j = S ; j < t ; ++j) p1[j] = Complex(0.0,0.0);
for(int j = 1 ; j <= T ; ++j) {
if(b[j] == i) p2[T - j] = Complex(1.0,0.0),++cnt;
else p2[T - j] = Complex(0.0,0.0);
}
for(int j = T ; j < t ; ++j) p2[j] = Complex(0.0,0.0);
FFT(p1,t,1);FFT(p2,t,1);
for(int j = 0 ; j < t ; ++j) p1[j] = p1[j] * p2[j];
FFT(p1,t,-1);
for(int j = 0 ; j < S ; ++j) {
if((int)(p1[j].r + 0.5) == cnt) vis[j] &= 1;
else vis[j] &= 0;
}
}
int ans = 0;
for(int i = 0 ; i < S ; ++i) if(vis[i]) ++ans;
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}

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

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

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

  2. 51nod 1565 模糊搜索 FFT

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

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

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

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

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

  5. 【51Nod 1244】莫比乌斯函数之和

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1244 模板题... 杜教筛和基于质因子分解的筛法都写了一下模板. 杜教筛 ...

  6. BZOJ 1565: [NOI2009]植物大战僵尸

    1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2317  Solved: 1071[Submit][Stat ...

  7. 51Nod 1268 和为K的组合

    51Nod  1268  和为K的组合 1268 和为K的组合 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 给出N个正整数组成的数组A,求能否从中选出若干个,使 ...

  8. 51Nod 1428 活动安排问题

    51Nod   1428  活动安排问题 Link: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1428 1428 活 ...

  9. 51Nod 1278 相离的圆

    51Nod 1278 相离的圆 Link: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1278 1278 相离的圆 基 ...

随机推荐

  1. UIScrollView的contentSize与contentOffset

    UIScrollView为了显示多于一个屏幕的内容或者超过你能放在内存中的内容. Scroll View为你处理缩小放大手势,UIScrollView实现了这些手势,并且替你处理对于它们的探测和回应. ...

  2. PHP常见的字符串方法

    PHP语言中的字符串函数也是一个比较易懂的知识.今天我们就为大家总结了将近12种PHP字符串函数,希望对又需要的朋友有所帮助,增加读者朋友的PHP知识库.   1.查找字符位置函数 strpos($s ...

  3. Chrome浏览器F12讲解

    Chrome浏览器相对于其他的浏览器而言,DevTools(开发者工具)非常强大.这节课将为大家介绍怎么利用Chrome浏览器的开发者工具进行HTTP请求分析 Chrome浏览器讲解 Chrome 开 ...

  4. 数据结构编程实验——chapter10-应用经典二叉树编程

    二叉树不仅结构简单.节省内存,更重要是是这种结构有利于对数据的二分处理.之前我们提过,在二叉树的基础上能够派生很多经典的数据结构,也是下面我们将进行讨论的知识点: (1)   提高数据查找效率的二叉排 ...

  5. 针对TCP连接异常断开的分析

    我们知道,一个基于TCP/IP的客户端-服务器的程序中,正常情况下,我会是启动服务器使其在一个端口上监听请求,等待客户端的连接:通过TCP的三次握手,客户端能够通过socket建立一个到服务器的连接: ...

  6. 关于JavaScript代码的执行效率总结

    Javascript是一门非常灵活的语言,我们可以随心所欲的书写各种风格的代码,不同风格的代码也必然也会导致执行效率的差异,开发过程中零零散散地接触到许多提高代码性能的方法,整理一下平时比较常见并且容 ...

  7. 新的玩具:Windows上的awesome

    平铺式窗口管理器 基于xwindow(Linux/Unix采用的图形系统)有成千上百种窗口管理器.其中有一类窗口管理器很古怪,所有应用程序的窗口没有互相遮挡,而是平铺到屏幕上,这类窗口管理器叫 平铺式 ...

  8. 20155230 2016-2017-2《Java程序设计》第六周学习总结

    20155230 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象. 从应用程序角度 ...

  9. 05.UIDynamic

    CHENYILONG Blog 05.UIDynamic Fullscreen © chenyilong. Powered by Postach.io Blog

  10. BFS 两个重要性质

    对于进行广度优先搜索的队列中,应该始终满足两个性质:   性质1:若队首为第i层拓展到的节点,则队列中最多只能存在第i层和第i+1层的节点,不可能出现3层节点.   性质2:队列中的元素会严格按照层数 ...