http://www.51nod.com/onlineJudge/questionCode.html#problemId=1565&noticeId=445588

有两个基因串S和T,他们只包含AGCT四种字符。现在你要找出T在S中出现了几次。

有一个门限值k≥0。T在S的第i(1≤i≤|S|-|T|+1)个位置中出现的条件如下:把T的开头和S的第i个字符对齐,然后T中的每一个字符能够在S中找到一样的,且位置偏差不超过k的,那么就认为T在S的第i个位置中出现。也就是说对于所有的 j (1≤j≤|T|),存在一个 p (1≤p≤|S|),使得|(i+j-1)-p|≤k 和[p]=T[j]都成立。

例如,根据这样的定义"ACAT"出现在"AGCAATTCAT"的第2,3和6的位置。

如果k=0,那么这个就是经典的字符串匹配问题。

现在给定门限和两个基因串S,T,求出T在S中出现的次数。

参考:https://www.cnblogs.com/ivorysi/p/9185805.html

首先用差分/线段树处理出每个位置是否能够匹配A/T/C/G,令$a[i][j]$存之,表示$i$这个字符在$j$这个位置是否能被匹配上。

然后我们处理模式串,令$b[i][j]$表示$i$这个字符在$j$这个位置是否存在。

然后就是套路了:BZOJ4259:残缺的字符串对大部分模糊匹配都是一个套路。

我们将模式串倒置然后末尾补0,令:

$f[k][i]=\sum_{j=0}^i(b[k][j]-a[k][i-j])b[k][j]$,当$f[k][j]==0$时说明我们只看$k$字符时模式串能被以$i$为终点的字符串所匹配上。

(我们后面多乘的那个是为了防止该位置不存在$k$字符所设置的。)

展开得到:

$f[k][i]=\sum_{j=0}^ib[k][j]^2-\sum_{j=0}^ia[k][i-j]b[k][j]$

后者是一个卷积,可以直接FFT,前者的2次方其实也可以直接拿掉(因为$1^2=1,0^2=0$)

显然当所有的字符情况下均满足$f[i]==0$的时候$i$就是一个合法位点了。

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef double dl;
const int N=4e5+;
const dl pi=acos(-1.0);
const int INF=;
struct complex{
dl x,y;
complex(dl xx=0.0,dl yy=0.0){
x=xx,y=yy;
}
complex operator +(const complex &b)const{
return complex(x+b.x,y+b.y);
}
complex operator -(const complex &b)const{
return complex(x-b.x,y-b.y);
}
complex operator *(const complex &b)const{
return complex(x*b.x-y*b.y,x*b.y+y*b.x);
}
};
void FFT(complex a[],int n,int on){
for(int i=,j=n>>;i<n-;i++){
if(i<j)swap(a[i],a[j]);
int k=n>>;
while(j>=k){j-=k;k>>=;}
if(j<k)j+=k;
}
for(int i=;i<=n;i<<=){
complex res(cos(-*pi*on/i),sin(-*pi*on/i));
for(int j=;j<n;j+=i){
complex w(,);
for(int k=j;k<j+i/;k++){
complex u=a[k],t=w*a[k+i/];
a[k]=u+t;a[k+i/]=u-t;
w=w*res;
}
}
}
if(on==-)
for(int i=;i<n;i++)a[i].x/=n;
}
inline int turn(char ch){
if(ch=='A')return ;
if(ch=='G')return ;
if(ch=='C')return ;
return ;
}
char s1[N],s2[N];
int n,m,k,t[N][];
int a[][N],b[][N],ans[N];
complex A[N],B[N];
bool can[N];
int main(){
scanf("%d%d%d",&n,&m,&k);
scanf("%s%s",s1,s2);
for(int i=;i<n;i++){
int w=turn(s1[i]);
int l=max(,i-k),r=min(n-,i+k);
t[l][w]++;t[r+][w]--;
}
for(int i=;i<n;i++)
for(int j=;j<;j++){
if(i)t[i][j]+=t[i-][j];
if(t[i][j]>)a[j][i]=;
}
for(int i=;i<m;i++)b[turn(s2[m-i-])][i]=; int len=;
while(len<n)len<<=;
for(int i=;i<;i++){
for(int j=;j<n;j++)
ans[j]=(j?ans[j-]:)+b[i][j]; for(int j=;j<len;j++){
A[j]=complex(a[i][j],);
B[j]=complex(b[i][j],);
}
FFT(A,len,);FFT(B,len,);
for(int j=;j<len;j++)A[j]=A[j]*B[j];
FFT(A,len,-);
for(int j=;j<n;j++)ans[j]-=(int)(A[j].x+0.5); for(int j=;j<n;j++)if(ans[j])can[j]=;
}
int cnt=;
for(int i=m-;i<n;i++)if(!can[i])cnt++;
printf("%d\n",cnt);
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

51NOD 1565:模糊搜索——题解的更多相关文章

  1. 51nod 1565 模糊搜索 FFT

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

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

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

  3. 【51nod】1565 模糊搜索

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

  4. 胡小兔的OI日志3 完结版

    胡小兔的 OI 日志 3 (2017.9.1 ~ 2017.10.11) 标签: 日记 查看最新 2017-09-02 51nod 1378 夹克老爷的愤怒 | 树形DP 夹克老爷逢三抽一之后,由于采 ...

  5. 51Nod1518 稳定多米诺覆盖 动态规划 插头dp 容斥原理

    原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1518.html 题目传送门 - 51Nod1518 题意 51Nod真是个好OJ ,题意概括的真好, ...

  6. HDU 6153 A Secret ( KMP&&DP || 拓展KMP )

    题意 : 给出两个字符串,现在需要求一个和sum,考虑第二个字符串的所有后缀,每个后缀对于这个sum的贡献是这个后缀在第一个字符串出现的次数*后缀的长度,最后输出的答案应当是 sum % 1e9+7 ...

  7. 51nod图论题解(4级,5级算法题)

    51nod图论题解(4级,5级算法题) 1805 小树 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 她发现她的树的点上都有一个标号(从1到n),这些树都在空 ...

  8. 51nod 1812 树的双直径 题解【树形DP】【贪心】

    老了-稍微麻烦一点的树形DP都想不到了. 题目描述 给定一棵树,边权是整数 \(c_i\) ,找出两条不相交的链(没有公共点),使得链长的乘积最大(链长定义为这条链上所有边的权值之和,如果这条链只有 ...

  9. 51NOD 1773:A国的贸易——题解

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1773 参考1:FWT讲解 https://www.cnblogs.com ...

随机推荐

  1. 两分钟了解Docker的优势

    本文来自网易云社区 我们主要从Docker对业务架构和生产实践的角度来分析. 随着业务规模的逐渐扩大,产品复杂度也随着增加,企业需要解决快速迭代.高可靠和高可用等问题,一个自然的选择是服务化的拆分,把 ...

  2. HardcodedDebugMode

    xmlns:tools="http://schemas.android.com/tools" tools:ignore="HardcodedDebugMode"

  3. Unity2017 经典游戏开发教程 算法分析与实现 (张帆 著)

    https://meta.box.lenovo.com/link/view/82c451b41ce34e81a4b34cb46747d3d5 第1章 熟悉Unity软件的操作 第2章 打地鼠 (已看) ...

  4. DEDEcms调用当前栏目顶级栏目url地址

    include/common.func.php 找到这个文件 在文件最下方加入以下代码: //获取顶级栏目url function GetTopTypeurl($id) { global $dsql; ...

  5. mysql新手入门随笔4

    40.子查询:出现在其他SQL语句里的SELECT语句 例如:SELECT sname,mark FROM student WHERE mark = (SELECT max(mark) FROM st ...

  6. <cerrno>

    文件头名称: <cerrno>(errno.h) 文件头描述: 文件内定义了如下的宏  errno 最后一个错误代码 加上其他至少的三个宏常量:EDOM,ERANGE 和EILSEQ 宏定 ...

  7. JavaScript基本概念(1)-声明提升

    声明提升: function > var > other var提升的时候,只是声明提升,但是赋值还是会在原来的位置. Javascript Hoisting:In javascript, ...

  8. [JSON].valueOf( keyPath )

    语法:[JSON].valueOf( keyPath ) 返回:[任意类型 | null] 说明:获取键名路径原值,它保留原始值的类型 示例: b = sysFile.binary("tes ...

  9. 在github上面创建属于自己的个性主页

    圈子里面越来越多的同事在github上面创建自己的项目文档,那里确实高手云集,海内外的技术大牛小牛们都在那儿有一席之地,为“helloword”贡献自己. 以上感慨略过... 这几日正想创建一个自己的 ...

  10. Java开发中用的比较多的数据结构

    java 中几种常用数据结构 2016年07月11日 09:11:27 阅读数:83211 标签: 数据结构java 更多 个人分类: 自行学习   JAVA中常用的数据结构(java.util. 中 ...