zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    JS BOM对象 History对象 Location对象
    JS 字符串对象 数组对象 函数对象 函数作用域
    JS 引入方式 基本数据类型 运算符 控制语句 循环 异常
    Pycharm Html CSS JS 快捷方式创建元素
    CSS 内外边距 float positio属性
    CSS 颜色 字体 背景 文本 边框 列表 display属性
    【Android】RxJava的使用(三)转换——map、flatMap
    【Android】RxJava的使用(二)Action
    【Android】RxJava的使用(一)基本用法
    【Android】Retrofit 2.0 的使用
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6561990.html
Copyright © 2011-2022 走看看