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

    luogu

    sol

    这种字符串匹配的问题显然可以把一个串(reverse)过来然后用(FFT)做吧。
    对每种字母分开考虑,设两个多项式(A(x),B(x)),其中

    [A(x)=sum_{i=0}^{n-1}[区间[i-k,i+k]内存在该种字符]x^i ]

    [B(x)=sum_{i=0}^{n-1}[t[i]为该种字符]x^i ]

    然后两个多项式卷一下就是这种字符在第(i)个位置上的匹配吧。
    最后对每次的系数求和,若恰好等于(|T|)则说明匹配成功。
    复杂度(O(4nlog n))

    code

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int _ = 8e5+5;
    const double Pi = acos(-1);
    struct Complex{
    	double rl,im;
    	Complex(){rl=im=0;}
    	Complex(double a,double b){rl=a,im=b;}
    	Complex operator + (Complex b)
    		{return Complex(rl+b.rl,im+b.im);}
    	Complex operator - (Complex b)
    		{return Complex(rl-b.rl,im-b.im);}
    	Complex operator * (Complex b)
    		{return Complex(rl*b.rl-im*b.im,rl*b.im+im*b.rl);}
    }w[_],a[_],b[_];
    int N,n,m,k,rev[_],l,tmp[_],ans[_],Ans;
    char s[_],t[_],fg[4]={'A','G','C','T'};
    void FFT(Complex *P,int opt)
    {
    	for (int i=0;i<N;++i) if (i<rev[i]) swap(P[i],P[rev[i]]);
    	for (int i=1;i<N;i<<=1)
    		for (int p=i<<1,j=0;j<N;j+=p)
    			for (int k=0;k<i;++k)
    			{
    				Complex W=w[N/i*k];W.im*=opt;
    				Complex X=P[j+k],Y=W*P[j+k+i];
    				P[j+k]=X+Y;P[j+k+i]=X-Y;
    			}
    	if (opt==-1) for (int i=0;i<N;++i) P[i].rl/=N;
    }
    int main()
    {
    	scanf("%d%d%d",&n,&m,&k);scanf("%s%s",s,t);reverse(t,t+m);
    	for (N=1;N<n+m;N<<=1) ++l;--l;
    	for (int i=0;i<N;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<l);
    	for (int i=0;i<N;++i) w[i]=Complex(cos(Pi*i/N),sin(Pi*i/N));
    	for (int zsy=0;zsy<4;++zsy)
    	{
    		for (int i=0;i<N;++i) a[i].rl=a[i].im=b[i].rl=b[i].im=0;
    		for (int i=0,pos=-1e9;i<n;++i)
    		{
    			if (s[i]==fg[zsy]) pos=i;
    			if (pos>=i-k) a[i].rl=1;
    		}
    		for (int i=n-1,pos=1e9;~i;--i)
    		{
    			if (s[i]==fg[zsy]) pos=i;
    			if (pos<=i+k) a[i].rl=1;
    		}
    		for (int i=0;i<m;++i) if (t[i]==fg[zsy]) b[i].rl=1;
    		FFT(a,1);FFT(b,1);
    		for (int i=0;i<N;++i) a[i]=a[i]*b[i];
    		FFT(a,-1);
    		for (int i=0;i<n;++i) ans[i]+=(int)(a[i].rl+0.5);
    	}
    	for (int i=0;i<n;++i) if (ans[i]==m) ++Ans;
    	printf("%d
    ",Ans);return 0;
    }
    
  • 相关阅读:
    flex自适应小例子
    hasOwnProperty 递归 简单回调 链式调用
    H5音频和视频
    html特殊字符
    css巧妙实现分隔线
    SQL Server中数据的存储
    SQL高级查询
    SQL SERVER查询到的数据转为Json格式
    SQL动态生成列
    SQL合并查询数据,以逗号分隔
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8728888.html
Copyright © 2011-2022 走看看