zoukankan      html  css  js  c++  java
  • 【51nod】1565 模糊搜索

    题解

    这个字符集很小,我们可以把每个字符拿出来做一次匹配,把第一个字符串处理每个出现过的该字符处理成一个区间加,即最后变成第一个字符串的该位置能够匹配某字符

    例如对于样例
    10 4 1
    AGCAATTCAT
    ACAT

    我们做A的时候,把第一个串处理成
    AAAAAA00AA0
    第二个串
    A0A0

    那么就变成第二个串从第一个串每个位置开始能不能匹配上第二个串所有的A了

    我们发现把第二个串反序之后和第一个串求一个卷积,那么第一个串每个位置如果系数等于第二个串该字符出现次数,那么证明这个位置可以匹配一个第二个串的末尾

    对于每个位置把所有字符集的答案&起来就好

    代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <set>
    #include <cmath>
    #define enter putchar('
    ')
    #define space putchar(' ')
    //#define ivorysi
    #define pb push_back
    #define MAXN 200005
    #define pii pair<int,int>
    #define mp make_pair
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 - '0' + c;
    	c = getchar();
        }
        res = res * f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) out(x / 10);
        putchar('0' + x % 10);
    }
    const db PI = acos(-1.0);
    char s1[MAXN],s2[MAXN];
    int K,S,T;
    int a[MAXN],b[MAXN],c[MAXN];
    bool vis[MAXN];
    struct Complex {
        db r,i;
        Complex(db real = 0.0,db image = 0.0) {
    	r = real;i = image;
        }
        friend Complex operator + (const Complex &a,const Complex &b) {
    	return Complex(a.r + b.r,a.i + b.i);
        }
        friend Complex operator - (const Complex &a,const Complex &b) {
    	return Complex(a.r - b.r,a.i - b.i);
        }
        friend Complex operator * (const Complex &a,const Complex &b) {
    	return Complex(a.r * b.r - a.i * b.i,a.r * b.i + a.i * b.r);
        }
    }p1[MAXN * 4],p2[MAXN * 4];
    void FFT(Complex *p,int L,int on) {
        for(int i = 1 , j = L / 2 ; i < L - 1 ; ++i) {
    	if(i < j) swap(p[i],p[j]);
    	int k = L / 2;
    	while(j >= k) {
    	    j -= k;
    	    k >>= 1;
    	}
    	j += k;
        }
        for(int h = 2 ; h <= L ; h <<= 1) {
    	Complex wn = Complex(cos(on * 2 * PI / h),sin(on * 2 * PI / h));
    	for(int k = 0 ; k < L ; k += h) {
    	    Complex w = Complex(1.0,0.0);
    	    for(int j = k ; j < k + h / 2 ; ++j) {
    		Complex u = p[j],t = p[j + h / 2] * w;
    		p[j] = u + t;
    		p[j + h / 2] = u - t;
    		w = w * wn;
    	    }
    	}
        }
        if(on == -1) {
    	for(int i = 0 ; i < L ; ++i) p[i].r /= L;
        }
    }
    int ci(char c) {
        if(c == 'A') return 1;
        else if(c == 'G') return 2;
        else if(c == 'C') return 3;
        else return 4;
    }
    void Init() {
        read(S);read(T);read(K);
        scanf("%s%s",s1 + 1,s2 + 1);
        for(int i = 1 ; i <= S ; ++i) a[i] = ci(s1[i]);
        for(int i = 1 ; i <= T ; ++i) b[i] = ci(s2[i]);
    }
    void Solve() {
        memset(vis,1,sizeof(vis));
        for(int i = 1 ; i <= 4;  ++i) {
    	int t = 1;
    	while(t <= S + T) t <<= 1;
    	int cnt = 0;
    	memset(c,0,sizeof(c));
    	for(int j = 1 ; j <= S ; ++j) {
    	    if(a[j] == i) c[max(1,j - K)]++,c[min(j + K + 1,S + 1)]--;
    	}
    	for(int j = 1 ; j <= S ; ++j) {
    	    c[j] += c[j - 1];
    	    if(c[j]) p1[j - 1] = Complex(1.0,0.0);
    	    else p1[j - 1] = Complex(0.0,0.0);
    	}
    	for(int j = S ; j < t ; ++j) p1[j] = Complex(0.0,0.0);
    	for(int j = 1 ; j <= T ; ++j) {
    	    if(b[j] == i) p2[T - j] = Complex(1.0,0.0),++cnt;
    	    else p2[T - j] = Complex(0.0,0.0);
    	}
    	for(int j = T ; j < t ; ++j) p2[j] = Complex(0.0,0.0);
    	FFT(p1,t,1);FFT(p2,t,1);
    	for(int j = 0 ; j < t ; ++j) p1[j] = p1[j] * p2[j];
    	FFT(p1,t,-1);
    	for(int j = 0 ; j < S ; ++j) {
    	    if((int)(p1[j].r + 0.5) == cnt) vis[j] &= 1;
    	    else vis[j] &= 0;
    	}
        }
        int ans = 0;
        for(int i = 0 ; i < S ; ++i) if(vis[i]) ++ans;
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
    }
    
  • 相关阅读:
    java读写文本文件
    django学习<二>:连接数据库
    【MongoDB】递归获取字段更新表达式,更新复杂数据类型对象
    【MongoDB】C#中的Mongo数据类型转换
    【MongoDB】 基于C#官方驱动2.2版的封装类
    【Python】 属性的 get 与 set 方法
    【基础知识】UML基础
    【C#】 知乎用户网络爬虫
    【C#】MVC项目中搭建WebSocket服务器
    【MongoDB】 Windows 安装
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9185805.html
Copyright © 2011-2022 走看看