一句话题意

给你两个串s、t,长度为n、m,字符集为"ATGC",当且仅

当[i - k; i + k]中存在一个j,使得s[j ] = t[x]时,s[i ]可以

和t[x]匹配,问t总共能与s的几个子串匹配

首先,字符集只有4,那么,令s_A[i]=0/1 表示在s中i位置能否和A匹配,同理t_A[i];

一类关于通配符匹配的字符串问题都是可以用FFT来解决的

以A字符为例,令

\[C[i]=\sum_{j=0}^{m-1}S[i+j]*T[j] , D=\sum_{i=0}^{m-1}T[i]
\]

则当c[i]==D时 以S[i]为首的一个子串内的A的位置与T的A的位置相同

\[T'[m-j-1]=T[j] , C'[m+i-1]=C[i]
\]

代入原式,则

\[C'[m+i-1]=\sum_{j=0}^{m-1}S[i+j]*T[m-j-1]
\]

成为了卷积形式

P.S. 也可以用bitset

#include<bits/stdc++.h>

using namespace std;

namespace Tzh{

	typedef double dd;
const char ch[]="0ATCG";
const int maxn=700010;
const dd pi=acos(-1);
int ans,vis[maxn],x,y,k,rev[maxn],n=1,len,sum;
string S,T; struct complex{
dd x,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};
}
complex operator *(const complex &b) const{
return (complex){x*b.x-y*b.y,x*b.y+y*b.x};
}
void init(){
x=0,y=0;
}
}s[maxn],t[maxn]; void init(){
for(int i=0;i<n;i++)
rev[i]=rev[i>>1]>>1|((i&1)<<(len-1));
} complex omg(int x,int flag){
return (complex){cos((dd)x*2*pi/n),(dd)sin((dd)x*2*pi/n)*flag};
} void FFT(complex *a,int type){
for(int i=0;i<n;i++) if(rev[i]>i) swap(a[i],a[rev[i]]);
for(int l=2,m=1;l<=n;m=l,l<<=1)
for(int i=0;i<n;i+=l)
for(int j=0;j<m;j++){
complex tt=omg(n/l*j,type)*a[i+j+m];
a[i+j+m]=a[i+j]-tt,a[i+j]=a[i+j]+tt;
}
if(type==-1)
for(int i=0;i<n;i++) a[i].x/=n;
} void work(){
ios::sync_with_stdio(false);
cin>>x>>y>>k;
cin>>S>>T; for(int i=0;i<=x;i++) vis[i]=1;
while(n<=x+y) n<<=1,len++; init();
for(int j=1;j<=4;j++){ int num=0;
for(int i=0;i<S.size();i++){
if(S[i]==ch[j]) num++;
if(i>k&&S[i-k-1]==ch[j]) num--;
s[i].x=(dd)(num>0);
} num=0,sum=0;
for(int i=S.size()-1;i>=0;i--){
if(S[i]==ch[j]) num++;
if(i+k+1<S.size()&&S[i+k+1]==ch[j]) num--;
s[i].x=max(s[i].x,(dd)(num>0));
}
for(int i=0;i<T.size();i++)
t[y-i-1].x=(dd)(T[i]==ch[j]),sum+=(int)t[y-i-1].x;
FFT(s,1),FFT(t,1);
for(int i=0;i<n;i++) s[i]=s[i]*t[i]; FFT(s,-1);
for(int i=0;i<x;i++) if((int)((dd)s[y+i-1].x+0.5)!=sum) vis[i]=0;
for(int i=0;i<n;i++) s[i].init(),t[i].init();
}
for(int i=0;i<x;i++) ans+=vis[i];
cout<<ans<<endl;
return ;
}
} int main(){
// freopen("1.in","r",stdin);
Tzh::work();
return 0;
}

CF_528D的更多相关文章

随机推荐

  1. 2.python中self详解(程序适用于python3版本)

    先介绍下Python中的类和实例面向对象最重要的概念就是类(class)和实例(instance),类(class)是抽象的模板,比如学生这个抽象的事物,可以用一个Student类来表示.而实例是根据 ...

  2. WEB前端学习资源清单

    常用学习资源 JS参考与基础学习系列 [MDN]JS标准参考 es6教程 JS标准参考教程 编程类中文书籍索引 深入理解JS系列 前端开发仓库 <JavaScript 闯关记> JavaS ...

  3. spring boot跨域问题

    跨域是指不同域名之间相互访问.跨域,指的是浏览器不能执行其他网站的脚本.它是浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制.也就是如果在A网站中,我们希望使用Ajax来获得B网站 ...

  4. 下载带有kali linux系统的VMware如何打开虚拟机?

    下载带有kali linux系统的VMware如何打开虚拟机? 一.安装VMware 温馨提示:如果你对虚拟机一无所知的话,最好不要自己下载kali linux系统的ISO镜像和VMware虚拟机,然 ...

  5. Linux基本操作

    1. ctr + alt + t 打开新的终端窗口2. ctr + shift + + 终端窗口字体放大3. ctr + - 终端窗口字体缩小4. ls : 查看目录下的文件信息5. pwd: 查看目 ...

  6. TypeError: argument 1 must be an integer, not _subprocess_handle/OSError: [WinError 87]

    Error Msg: Traceback (most recent call last): File "c:\python27\lib\site-packages\celery\worker ...

  7. opencv : imread()的应用

    概述: imread()是opencv中用于读取图片的一个工具.怎么读取图片看似一个很简单的工作,但实际上也有一些细节需要我们注意,以避免在后续的操作中出现bug. 函数原型: 函数原型: Mat i ...

  8. VS2019 实用操作

    本文列出了在编写程序过程中的几个非常实用的操作方式,通过这些操作方式,可以在一定程度上减少重复操作.提高编码效率.改善编程体验. 列模式操作 列操作是一项很常用且实用的功能,可以一次性修改不同的行. ...

  9. 移除 iview的Table组件固定两头后box-shadow阴影效果

    .ivu-table-fixed{ box-shadow:0 0 0 #fff; }

  10. Python----简单线性回归

    简单线性回归 1.研究一个自变量(X)和一个因变量(y)的关系   简单线性回归模型定义:y=β0+β1x+ε 简单线性回归方程:E(y)=β0+β1x 其中: β0为回归线的截距 β1为回归线的斜率 ...