• UVALive 4671 K-neighbor substrings 巧用FFT


    UVALive4671   K-neighbor substrings   给定一个两个字符串A和B B为模式串。问A中有多少不同子串与B的距离小于k 所谓距离就是不同位的个数。

    由于字符串只包含a和b 我们可以换做0和1 将B反转 进行大整数乘法(卷积) 就可以轻松得出不同的位数。只有FFT能在nlogn时间内完成大整数乘法。

    要求不同的子串,再进行一次字符串散列即可。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<complex>
    //使用FFT时注意精度问题和数组大小 
    using namespace std;
    typedef long long int LL;
    const double pi=acos(-1.0);
    struct Complex {
        double r, i;
        Complex(double _r, double _i) {
            r = _r;
            i = _i;
        }
        double real()
        	{
        	 return r;
    		}
    	double ii()
    		{
    			return i;
    		}
        Complex operator + (const Complex &c) {
            return Complex(c.r + r, c.i + i);
        }
        Complex operator - (const Complex &c) {
            return Complex(r - c.r, i - c.i);
        }
        Complex operator * (const Complex &c) {
            return Complex(c.r * r - c.i * i, c.r * i + c.i * r);
        }
        Complex operator / (const int &c) {
            return Complex(r / c, i / c);
        }
        Complex(){}
    };
    void build(Complex _P[],Complex P[],LL n,LL m,LL curr,LL &cnt)
    {
     if(n==m){_P[curr]=P[cnt++];}
     	else {build(_P,P,n,m*2,curr,cnt);build(_P,P,n,m*2,curr+m,cnt);}
     
    }
    const LL maxn=300000;
    void FFT(Complex P[],LL n,LL oper)//返回结果向左靠齐 最后结果除n 
    {
     static Complex _P[maxn];
     LL cnt=0;
     build(_P,P,n,1,0,cnt);copy(_P,_P+n,P);
     for(LL d=0;(1<<d)<n;d++)
     	{
     	 LL m=1<<d;
     	 LL m2=m*2;
     	 double p0=pi/m*oper;
     	 Complex unit_p0=Complex(cos(p0),sin(p0));
     	 for(LL i=0;i<n;i+=m2)
     	 	{
     	 	 Complex unit=Complex(1,0);
     	 	 for(LL j=0;j<m;j++)
     	 	 	{
     	 	 	 Complex &P1=P[i+j+m],&P2=P[i+j];
     	 	 	 Complex t=unit*P1;
     	 	 	 P1=P2-t;
     	 	 	 P2=P2+t;
     	 	 	 unit=unit*unit_p0;
    			}
    		}
    	}
    }
    void himult(Complex p1[],Complex p2[],LL n,Complex ans[])
    {
     
     FFT(p1,n,1);FFT(p2,n,1);
     for(LL i=0;i<=n;i++)
        ans[i]=p1[i]*p2[i];
     FFT(ans,n,-1);	
    }
    char a[131072*2],b[131072*2];
    Complex av[131072*4],bv[131072*2+1],ans1[131072*2+1];
    unsigned long long int  ha[200000],xp[200000];
    const int seed=3;
    set<unsigned long long int >vise;
    bool hash(int	 l,int  r)
    {
     unsigned long long int  nowv= ha[r+1]-ha[l]*xp[r-l+1];
     if(vise.count(nowv)==0){vise.insert(nowv);return false;}
     	else return true;
    }
    int main()
    {
     freopen("t.txt","r",stdin);
     xp[0]=1;
     for(int i=1;i<=100000;i++)
     	xp[i]=xp[i-1]*seed;
     int ii=0;
     while(1)
     	{  ii++;
     	   vise.clear();
     	   int k;
     	   scanf("%d",&k);
     	   if(k==-1)break;
     	   memset(a,0,sizeof(a));memset(b,0,sizeof(b));
     	   scanf("%s%s",&a,&b);
           int la=strlen(a),lb=strlen(b);
           int len=1;
           while(len<=la+lb)len<<=1;
    	   for(int i=0;i<la;i++)
    	      av[i]=Complex(a[i]=='a'?1:-1,0);
    	   for(int i=la;i<=len;i++)av[i]=Complex(0,0);
    	   for(int i=0;i<lb;i++)
    	      bv[lb-i-1]=Complex(b[i]=='a'?1:-1,0);
    	   for(int i=lb;i<=len;i++)
    	   	  bv[i]=Complex(0,0);
    	   memset(ans1,0,sizeof(ans1));
    	   himult(av,bv,len,ans1);
    	   int anss=0;
    	   ha[0]=0;
    	   for(int i=0;i<la;i++)
    	   		ha[i+1]=ha[i]*seed+a[i];  
    	   for(int i=0;i+lb<=la;i++)
    	   		{
    	   		 if(hash(i,i+lb-1))continue;
    	   		 int nue=(int)(ans1[i+lb-1].r/len+0.5);
    	   		 if(lb-nue<=k*2)anss++;
    			}      	   
    	   printf("Case %d: %d
    ",ii,anss);
    	}
     return 0;
    }
    

      

  • 相关阅读:
    Git 分支开发规范
    小程序技术调研
    弹性布局
    vue 自定义指令的魅力
    记一次基于 mpvue 的小程序开发及上线实战
    mpvue学习笔记-之微信小程序数据请求封装
    微信小程序开发框架 Wepy 的使用
    Hbuilder 开发微信小程序的代码高亮
    luogu3807 【模板】 卢卡斯定理
    luogu1955 [NOI2015] 程序自动分析
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6561990.html
Copyright © 2020-2023  润新知