分析

我们发现难点其实是在如何处理距离为 的节点也可以匹配的问题。我们可以把四个字符拆开,一样的我们定义一个新的距离函数就可以了 。那么按照套路反转 或者 。我们就得到了一个卷积形式,那么最后的时间复杂度为

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 8e5 + 100,P = 998244353;
int limit = 1,R[N],L = 0,K,n,m;
char A[N],B[N];
int cnt[N],g[N],f[N];
int ksm(int a,int b) {
    int x = 1;for(;b;b >>= 1,a = a * 1ll * a % P) {
        if(b & 1) x = x * 1ll * a % P;
    }return x;
}
void NTT(int *a,int type) {
    for(int i = 0;i < limit;i++) if(i < R[i]) swap(a[i],a[R[i]]);
    for(int mid = 1;mid < limit;mid <<= 1) {
        int wn = ksm(3,(P-1)/(mid << 1));
        for(int i = 0;i < limit;i += (mid << 1)) {
            for(int j = 0,w = 1;j < mid;j++,w = w * 1ll * wn % P) {
                int x = a[i + j],y = w * 1ll * a[i + j + mid] % P;
                a[i + j] = (x + y) % P;a[i + j + mid] = (x - y + P) % P;
            }  
        }
    }
    if(type == -1) {
        int Inv = ksm(limit,P - 2);reverse(a + 1,a + limit);
        for(int i = 0;i < limit;i++) a[i] = a[i] * 1ll * Inv % P;
    }
}
void solve(char pos) {
    memset(f,0,sizeof(f));memset(g,0,sizeof(g));
    for(int i = 0,last = -1e9;i < n;i++) {if(A[i] == pos) last = i;if(i - last <= K) f[i] = 1;}
    for(int i = n - 1,last = 1e9;i >= 0;i--) {if(A[i] == pos) last = i;if(last - i <= K) f[i] = 1;}
    for(int i = 0;i < m;i++) if(B[i] == pos) g[i] = 1;
    reverse(g,g + m);NTT(f,1);NTT(g,1);
    for(int i = 0;i < limit;i++) f[i] = 1ll * f[i] * g[i] % P;
    NTT(f,-1);//for(int i = 0;i < n;i++) cout << f[i] << " ";cout << endl;
    for(int i = 0;i < n;i++) cnt[i] += f[i];
}
int main() {
    scanf("%d%d%d%s%s",&n,&m,&K,A,B);
    while(limit <= n + m - 2) limit <<= 1,L++;
    for(int i = 0;i < limit;i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
    solve('A');solve('C');solve('G');solve('T');
    int ans = 0;
    for(int i = 0;i < n;i++) if(cnt[i] == m) ans++;
    cout << ans << endl;
}