首先预处理一个 0 / 1数组, 表示这个位置能不能与 A / C / G / T 匹配
由于字符集很小, 所以我们可以一个字符一个字符处理
我们将 B 串是当前枚举字符的位置赋成1, 那么两个都是1就可以匹配
于是 FFT 将它们卷起来, 并且将4次处理的多项式相加, 如果某一位系数为 m, 那么每个字符都匹配上了
#include<bits/stdc++.h>
#define N 1000050
using namespace std;
const double PI = acos(-1.0);
struct Node{
double x, y;
Node(double _x = 0, double _y = 0){ x = _x, y = _y;}
Node operator + (const Node &a){ return Node(x + a.x, y + a.y);}
Node operator - (const Node &a){ return Node(x - a.x, y - a.y);}
Node operator * (const Node &a){ return Node(x * a.x - y * a.y, x * a.y + y * a.x);}
}A[N], B[N];
int a[N], S[N], n, m, k; char s1[N], s2[N];
int up, bit, rev[N];
void Init(int len){ up = 1, bit = 0;
while(up <= len) up <<= 1, bit++;
for(int i=0; i<up; i++) rev[i] = (rev[i>>1]>>1) | ((i&1)<<(bit-1));
}
void FFT(Node *a, int inv){
for(int i=0; i<up; i++) if(i < rev[i]) swap(a[i], a[rev[i]]);
for(int i=1; i<up; i<<=1){
Node wn(cos(PI/i), inv * sin(PI/i));
for(int j=0; j<up; j+=(i<<1)){
Node w(1, 0);
for(int k=0; k<i; k++, w=w*wn){
Node x = a[k+j], y = w * a[k+j+i];
a[k+j] = x + y; a[k+j+i] = x - y;
}
}
}
}
int main(){
scanf("%d%d%d", &n, &m, &k);
scanf("%s%s", s1, s2); Init(n + m + 1);
for(int now=0; now<4; now++){
char op; if(now == 0) op = 'A'; if(now == 1) op = 'C'; if(now == 2) op = 'G'; if(now == 3) op = 'T';
for(int i=0; i<up; i++) A[i] = B[i] = Node(0, 0);
for(int i=0; i<n; i++) a[i] = (s1[i] == op) ? 1 : 0, a[i] += a[i-1];
for(int i=0; i<n; i++){
int l = max(0, i - k), r = min(n-1, i + k);
if(a[r] - (!l ? 0 : a[l-1]) > 0) A[i] = Node(1, 0); else A[i] = Node(0, 0);
}
for(int i=0; i<m; i++) B[m-i-1] = Node(s2[i] == op ? 1 : 0, 0);
FFT(A, 1); FFT(B, 1); for(int i=0; i<up; i++) A[i] = A[i] * B[i];
FFT(A, -1); for(int i=m-1; i<n+m; i++) S[i] += int(A[i].x / up + 0.5);
}
int ans = 0;
for(int i=m-1; i<n+m; i++) if(S[i] == m) ans++;
printf("%d", ans); return 0;
}