zoukankan      html  css  js  c++  java
  • CF528D. Fuzzy Search [FFT]

    CF528D. Fuzzy Search

    题意:DNA序列,在母串s中匹配模式串t,对于s中每个位置i,只要s[i-k]到s[i+k]中有c就认为匹配了c。求有多少个位置匹配了t


    预处理(f[i][j])表示位置i可以匹配字符j
    分别考虑每一个字符c,对s的每个位置i求出用(s[i,i+m-1])匹配t,这个字符匹配了几次
    (a_i=[s的位置i匹配c], b_i=[t_i=c])
    那么c的匹配次数就是(c_j=sumlimits_{i=0}^{m-1}a_{j+i}b_i),位置i匹配了t当且仅当四种字符的匹配次数和等于t的长度m


    ~~这时候就可以考虑bitset暴力过了~~

    一个常用技巧是,反转模式串(或母串),然后就成了卷积的形式:

    [c_j=sumlimits_{i=0}^{m-1}a_{j+i}b_{m-1-i}=D_{m+j-1} ]

    这样计算是没有问题的,因为b只有([0,m-1])有值其他地方为0


    注意处理每个字符前memset a和b!!!!!

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=(1<<20)+5, INF=1e9;
    const double PI=acos(-1);
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    struct meow{
    	double x, y;
    	meow(double a=0, double b=0):x(a), y(b){}
    };
    meow operator +(meow a, meow b) {return meow(a.x+b.x, a.y+b.y);}
    meow operator -(meow a, meow b) {return meow(a.x-b.x, a.y-b.y);}
    meow operator *(meow a, meow b) {return meow(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x);}
    meow conj(meow a) {return meow(a.x, -a.y);}
    typedef meow cd;
    
    namespace FFT{
    	int n, rev[N];
    	void ini(int lim) {
    		n=1; int k=0;
    		while(n<lim) n<<=1, k++;
    		for(int i=0; i<n; i++) rev[i] = (rev[i>>1]>>1) | ((i&1)<<(k-1));
    	}
    	void dft(cd *a, int flag) {
    		for(int i=0; i<n; i++) if(i<rev[i]) swap(a[i], a[rev[i]]);
    		for(int l=2; l<=n; l<<=1) {
    			int m=l>>1; 
    			cd wn = meow(cos(2*PI/l), flag*sin(2*PI/l));
    			for(cd *p=a; p!=a+n; p+=l) {
    				cd w(1, 0);
    				for(int k=0; k<m; k++) {
    					cd t = w*p[k+m];
    					p[k+m] = p[k] - t;
    					p[k] = p[k] + t;
    					w=w*wn;
    				}
    			}
    		}
    		if(flag==-1) for(int i=0; i<n; i++) a[i].x/=n;
    	}
    	void mul(cd *a, cd *b) {
    		dft(a, 1); dft(b, 1);
    		for(int i=0; i<n; i++) a[i]=a[i]*b[i];
    		dft(a, -1);
    	}
    }using FFT::mul; using FFT::ini;
    
    int n, m, k, lim, f[N][5], cnt[5], id[300];
    cd a[N], b[N], c[N];
    char s[N], t[N];
    int ans[N];
    void solve(int now) { 
    	memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b));
    	for(int i=0; i<n; i++) a[i].x = f[i][now];
    	for(int i=0; i<m; i++) b[m-1-i].x = id[(int)t[i]]==now; 
    	mul(a, b);
    	for(int i=0; i<n; i++) ans[i] += int(a[m-1+i].x+0.5);
    }
    int main() {
    	freopen("in","r",stdin);
    	n=read(); m=read(); k=read(); 
    	lim=n+m-1; ini(lim);
    	scanf("%s%s",s,t);
    	id['A']=0; id['T']=1; id['C']=2; id['G']=3;
    	int l=0, r=0; cnt[ id[(int)s[0]] ]++;
    	for(int i=0; i<n; i++) {
    		while(l<i-k) cnt[ id[(int)s[l++]] ]--;
    		while(r<n-1 && r<i+k) cnt[ id[(int)s[++r]] ]++;
    		for(int j=0; j<4; j++) if(cnt[j]) f[i][j]=1;
    	}
    	for(int i=0; i<4; i++) solve(i);
    	int sum=0;
    	for(int i=0; i<n; i++) if(ans[i]==m) sum++;
    	printf("%d",sum);
    }
    
  • 相关阅读:
    51Nod-1006【LCS】+【输出路径】模板题
    POJ 2250 Compromise【LCS】+输出路径
    洛谷 P1387 最大正方形 【dp】(经典)
    【hdu】4521 小明序列【LIS变种】【间隔至少为d】
    HDU 1025 城市供应 【LIS】
    hdu 2191 悼念512汶川大地震遇难同胞 【多重背包】(模板题)
    HDU 2159 FATE【二维完全背包】
    POJ 1384 Piggy-Bank【完全背包】+【恰好完全装满】(可达性DP)
    洛谷 P1474 货币系统 Money Systems(经典)【完全背包】+【恰好装满的最大方案数量】
    洛谷 P1057 传球游戏 【dp】(经典)
  • 原文地址:https://www.cnblogs.com/candy99/p/6648736.html
Copyright © 2011-2022 走看看