传送门
fftfftfft好题。
题意简述:给两个字符串s,ts,ts,t,问ttt在sss中出现了几次,字符串只由A,T,C,GA,T,C,GA,T,C,G构成。
两个字符匹配的定义:
当si−k,si−k+1,...,si+k−1,si+ks_{i-k},s_{i-k+1},...,s_{i+k-1},s_{i+k}si−k,si−k+1,...,si+k−1,si+k中存在至少一个字符使得sj=tls_j=t_lsj=tl时,我们称sis_isi与tlt_ltl匹配。
题目会给出n,m,k,s,tn,m,k,s,tn,m,k,s,t
思路:
我们把这四种字符拆开分别求解。
设当前处理的是字符xxx,那么我们将s,ts,ts,t中分别可以跟字符xxx匹配的位置标记成为111,其余不能匹配的位置标记成000。
这样一来就可以用经典的套路来统计答案啦!
我们把操作之后的ttt翻转,然后把s,ts,ts,t做多项式乘法,算出来如果某一位hhh的值等于ttt中111的个数说明sh,h+∣t∣−1=ts_{h,h+|t|-1}=tsh,h+∣t∣−1=t,然后我们做四遍把 四次都匹配的位置数统计出来即可。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
struct Cp{
double x,y;
friend inline Cp operator+(const Cp&a,const Cp&b){return (Cp){a.x+b.x,a.y+b.y};}
friend inline Cp operator-(const Cp&a,const Cp&b){return (Cp){a.x-b.x,a.y-b.y};}
friend inline Cp operator*(const Cp&a,const Cp&b){return (Cp){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};}
friend inline Cp operator/(const Cp&a,const double&b){return (Cp){a.x/b,a.y/b};}
friend inline Cp operator*(const Cp&a,const double&b){return (Cp){a.x*b,a.y*b};}
};
const int N=2e5+5;
vector<Cp>A,B;
int lim,tim,n,m,K,a[N],b[N],ans[N];
char s[N];
vector<int>pos;
inline void init(const int&up){
lim=1,tim=0;
while(lim<=up)lim<<=1,++tim;
pos.resize(lim),A.resize(lim),B.resize(lim);
for(ri i=0;i<lim;++i)pos[i]=(pos[i>>1]>>1)|((i&1)<<(tim-1));
}
const double pi=acos(-1.0);
inline void fft(vector<Cp>&a,const int&type){
Cp wn,w,a0,a1;
for(ri i=0;i<lim;++i)if(i<pos[i])swap(a[i],a[pos[i]]);
for(ri mid=1;mid<lim;mid<<=1){
wn=(Cp){cos(pi/mid),sin(pi/mid*type)};
for(ri j=0,len=mid<<1;j<lim;j+=len){
w=(Cp){1,0};
for(ri k=0;k<mid;++k,w=w*wn)a0=a[j+k],a1=w*a[j+k+mid],a[j+k]=a0+a1,a[j+k+mid]=a0-a1;
}
}
if(type==-1)for(ri i=0;i<lim;++i)a[i]=a[i]/lim;
}
struct poly{
vector<Cp>a;
poly(int k=0,Cp x=(Cp){0,0}){a.resize(k+1),a[k]=x;}
inline Cp&operator[](const int&k){return a[k];}
inline const Cp&operator[](const int&k)const{return a[k];}
inline int deg()const{return a.size()-1;}
inline poly extend(const int&k){poly ret=*this;return ret.a.resize(k+1),ret;}
friend inline poly operator*(const poly&a,const poly&b){
poly ret;
int n=a.deg(),m=b.deg();
init(a.deg()+b.deg());
for(ri i=0;i<=n;++i)A[i]=a[i];
for(ri i=n+1;i<lim;++i)A[i]=(Cp){0,0};
for(ri i=0;i<=m;++i)B[i]=b[i];
for(ri i=m+1;i<lim;++i)B[i]=(Cp){0,0};
fft(A,1),fft(B,1);
for(ri i=0;i<lim;++i)A[i]=A[i]*B[i];
return fft(A,-1),ret.a=A,ret;
}
};
inline int calc(char x){return x=='A'?1:(x=='T'?2:(x=='C'?3:4));}
inline void solve(int t){
poly x(n-1),y(m-1);
int cnt=0;
for(ri l=1,r=0,i=1;i<=n;++i){
while(i+K>r&&r<=n){
++r;
if(a[r]==t)++cnt;
}
if(i-K>l){
if(a[l]==t)--cnt;
++l;
}
x[i-1].y=0;
x[i-1].x=cnt>0;
}
int tot=0;
for(ri i=1;i<=m;++i)y[i-1].x=b[i]==t,y[i-1].y=0,tot+=y[i-1].x;
reverse(y.a.begin(),y.a.end());
x=x*y;
for(ri i=0;i+m-1<=n;++i)if((int)(x[i+m-1].x+0.5)==tot)++ans[i+1];
}
int main(){
freopen("lx.in","r",stdin);
scanf("%d%d%d",&n,&m,&K);
scanf("%s",s+1);
for(ri i=1;i<=n;++i)a[i]=calc(s[i]);
scanf("%s",s+1);
for(ri i=1;i<=m;++i)b[i]=calc(s[i]);
for(ri i=1;i<=4;++i)solve(i);
int cnt=0;
for(ri i=1;i<=n;++i)cnt+=ans[i]==4;
cout<<cnt;
return 0;
}