分别仅考虑 ,把匹配成功的位置取个交集就可以。
使用 FFT 来完成字符串匹配。
现在仅考虑 ,把 中不会和 匹配上的位置上的字符设为 ,把 中不是 的字符设为 ,则匹配函数 (其中 来自 , 来自 )要满足:
- ;
- ;
- ;
- .
这样的 才能满足匹配成功值为 ,否则大于 .
设:
-
中的 值为 , 值为 ;
-
中的 值为 , 值为 ;
-
.
对于每个字符只需要一次 FFT 就可以了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
typedef long long ll;
typedef double ld;
inline int Max(int x, int y) { return x > y ? x : y; }
inline int Min(int x, int y) { return x < y ? x : y; }
const int N = 800010;
const ld pi = acos(-1.0);
struct cpx {
ld x, y;
cpx(ld xx = 0, ld yy = 0) { x = xx; y = yy; }
};
cpx operator + (cpx a, cpx b) { return cpx(a.x + b.x, a.y + b.y); }
cpx operator - (cpx a, cpx b) { return cpx(a.x - b.x, a.y - b.y); }
cpx operator * (cpx a, cpx b) { return cpx(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); }
cpx *getw(int n, int type) {
static cpx w[N/2];
w[0] = cpx(1, 0); w[1] = cpx(cos(2 * pi / n), sin(2 * pi / n) * type);
for(int i = 2; i < n/2; ++i) w[i] = w[i-1] * w[1];
return w;
}
int p[N];
void FFT(cpx *a, int n, int type) {
for(int i = 0; i < n; ++i) if(i < p[i]) std::swap(a[i], a[p[i]]);
for(int i = 1; i < n; i <<= 1) {
cpx *w = getw(i << 1, type);
for(int j = 0; j < n; j += i << 1) {
cpx *b = a + j, *c = b + i;
for(int k = 0; k < i; ++k) {
cpx v = w[k] * c[k];
c[k] = b[k] - v;
b[k] = b[k] + v;
}
}
}
if(type == -1) for(int i = 0; i < n; ++i) a[i].x /= n;
}
void mul(int *a, int *b, int *c, int n, int m) {
static cpx f[N], g[N];
int len = 1, ct = 0;
while(len <= n + m) len <<= 1, ++ct;
for(int i = 0; i < len; ++i) p[i] = (p[i>>1]>>1) | ((i&1) << (ct-1));
for(int i = 0; i < len; ++i) f[i] = g[i] = cpx(0, 0);
for(int i = 0; i < n; ++i) f[i] = cpx(a[i], 0);
for(int i = 0; i < m; ++i) g[i] = cpx(b[i], 0);
FFT(f, len, 1);
FFT(g, len, 1);
for(int i = 0; i < len; ++i) f[i] = f[i] * g[i];
FFT(f, len, -1);
for(int i = 0; i < len; ++i) c[i] = (int)(f[i].x+0.5);
}
int n, m, k;
int id[300], c[4][N], A[4][N];
char s[N], t[N];
int f[N], g[N];
signed main() {
scanf("%d%d%d", &n, &m, &k);
id['A'] = 0, id['G'] = 1, id['C'] = 2, id['T'] = 3;
scanf("%s", s); scanf("%s", t);
for(int i = 0; i < n; ++i) {
s[i] = id[(int)s[i]]; t[i] = id[(int)t[i]];
++c[(int)s[i]][Max(i-k, 0)];
--c[(int)s[i]][Min(i+k+1, n)];
}
for(int i = 1; i < n; ++i) for(int j = 0; j < 4; ++j) c[j][i] += c[j][i-1];
for(int o = 0; o < 4; ++o) {
for(int i = 0; i < n; ++i)
f[i] = c[o][i] ? 0 : 1;
for(int i = 0; i < m; ++i)
g[i] = t[i] == o ? 1 : 0;
std::reverse(g, g + m);
mul(f, g, A[o], n, m);
}
int ans = 0;
for(int i = m-1; i < n; ++i)
if(!A[0][i] && !A[1][i] && !A[2][i] && !A[3][i])
++ans;
printf("%d\n", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?