「题解」Codeforces 528D Fuzzy Search

「题解」Codeforces 528D Fuzzy Search

分别仅考虑 A,C,G,T,把匹配成功的位置取个交集就可以。

使用 FFT 来完成字符串匹配。

现在仅考虑 A,把 S 中不会和 A 匹配上的位置上的字符设为 o,把 T 中不是 A 的字符设为 #,则匹配函数 C(x,y) (其中 x 来自 Sy 来自 T)要满足:

  • =0,x=A,y=A
  • =0,x=A,y=#
  • >0,x=o,y=A
  • =0,x=o,y=#

这样的 C 才能满足匹配成功值为 0,否则大于 0

设:

  • S 中的 A 值为 0o 值为 1

  • T 中的 A 值为 1# 值为 0

  • C(x,y)=xy

对于每个字符只需要一次 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;
}
posted @   do_while_true  阅读(33)  评论(0编辑  收藏  举报
编辑推荐:
· .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吗?

This blog has running: 1845 days 1 hours 33 minutes 57 seconds

点击右上角即可分享
微信分享提示