先将t串反转,然后对每一个字母做多项式乘法。。。全加起来就是t串匹配的最大字母数。。。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cmath> #include <time.h> #define maxn 700005 #define maxm 1000005 #define eps 1e-7 #define mod 1000000007 #define INF 0x3f3f3f3f #define PI (acos(-1.0)) #define lowbit(x) (x&(-x)) #define mp make_pair #define ls o<<1 #define rs o<<1 | 1 #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R #define pii pair<int, int> #pragma comment(linker, "/STACK:16777216") typedef long long LL; typedef unsigned long long ULL; //typedef int LL; using namespace std; LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;} LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;} //head struct complex { double r, i; complex(double r = 0, double i = 0) : r(r), i(i) {} complex operator + (const complex b) const { return complex(r + b.r, i + b.i); } complex operator - (const complex b) const { return complex(r - b.r, i - b.i); } complex operator * (const complex b) const { return complex(r * b.r - i * b.i, r * b.i + i * b.r); } }a[maxn], b[maxn], res[maxn]; void fft(complex y[], int len, int on) { for(int i = 1, j = len / 2; i < len-1; i++) { if(i < j) swap(y[i], y[j]); int k = len / 2; while(j >= k) { j -= k; k /= 2; } j += k; } for(int i = 2; i <= len; i <<= 1) { complex wn = complex(cos(-on * 2 * PI / i), sin(-on * 2 * PI / i)); for(int j = 0; j < len; j += i) { complex w = complex(1.0, 0.0); for(int k = j; k < j + i / 2; k++) { complex u = y[k]; complex t = w * y[k + i / 2]; y[k] = u + t; y[k + i / 2] = u - t; w = w * wn; } } } if(on == -1) for(int i = 0; i < len; i++) y[i].r /= len; } char s[maxn]; char t[maxn]; int sum[maxn]; int n, m, kk; void read() { scanf("%d%d%d", &n, &m, &kk); scanf("%s%s", s, t); } void solve(char c, int len) { memset(a, 0, sizeof a); memset(b, 0, sizeof b); memset(sum, 0, sizeof sum); for(int i = 0; i < n; i++) sum[i+1] = s[i] == c; for(int i = 1; i <= n; i++) sum[i] += sum[i-1]; for(int i = 0; i < n; i++) { int mi = max(0, i - kk); int mx = min(n - 1, i + kk) + 1; if(sum[mx] - sum[mi]) a[i].r = 1.0; } for(int i = 0; i < m; i++) b[i].r = t[i] == c; fft(a, len, 1); fft(b, len, 1); for(int i = 0; i < len; i++) res[i] = res[i] + a[i] * b[i]; } void work() { reverse(t, t+m); int mx = max(n, m); int len = 1; while(len < 2 * mx) len <<= 1; solve('A', len); solve('C', len); solve('G', len); solve('T', len); fft(res, len, -1); int ans = 0; for(int i = m-1; i < n; i++) if((int)(res[i].r + 0.5) >= m) ans++; printf("%d\n", ans); } int main() { read(); work(); return 0; }