[压位 || FFT] 【Hillan 的题】简单字符串匹配
2017-10-11 13:19
281 查看
不匹配度就是异或后数1的个数。可以压位优化一下,需要对于任意为开始,每 16 压一起。预处理 216 以内的数中1的个数。
这样可以优化到 O(n∗Q/16),是可以过的。
对于最后1分的包,考虑答案为 ∑(S1i−S2j)2=∑S12i+∑S22i−2∑S1i∗S2j
只需求 Fi=∑i+N−1j=iS1j∗S2j,然后变形一下,把 S1 反一下:
Fi=∑j=0i+n−1S1′i−j∗S2j 然后 FFT。
这样可以优化到 O(n∗Q/16),是可以过的。
对于最后1分的包,考虑答案为 ∑(S1i−S2j)2=∑S12i+∑S22i−2∑S1i∗S2j
只需求 Fi=∑i+N−1j=iS1j∗S2j,然后变形一下,把 S1 反一下:
Fi=∑j=0i+n−1S1′i−j∗S2j 然后 FFT。
#include<cstdio> #include<cmath> #include<cstring> #include<bitset> #include<algorithm> using namespace std; const int maxn=2000005; inline char gc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int getint(){ char ch=gc(); int res=0; while(!('0'<=ch&&ch<='9')) ch=gc(); while('0'<=ch&&ch<='9') res=(res<<1)+(res<<3)+ch-'0', ch=gc(); return res; } int n,m,Q,last_ans,b1[18][maxn],b2[18][maxn],cnt[(1<<16)+5],S1[maxn],S2[maxn],sum1,sum2[maxn]; int Get(int a[],int L,int R){ int res=0; for(int i=L;i<=R;i++) res|=(a[i]<<i-L); return res; } void Pre(){ for(int i=0;i+15<=n;i+=16) b1[0][i/16]=Get(S1,i,i+15); for(int j=1;j<=15;j++) for(int i=j;i+15<=n;i+=16) b1[j][i/16]=b1[j-1][i/16]>>1|(S1[i+15]<<15); for(int i=0;i+15<=m;i+=16) b2[0][i/16]=Get(S2,i,i+15); for(int j=1;j<=15;j++) for(int i=j;i+15<=m;i+=16) b2[j][i/16]=b2[j-1][i/16]>>1|(S2[i+15]<<15); for(int i=1;i<=(1<<16)-1;i++){ int t=i; do cnt[i]+=t&1, t>>=1; while(t); } } int Solve(int p1,int p2,int len){ int res=0,now; for(now=1;now+15<=len;now+=16) res+=cnt[b1[(p1+now-1)%16][(p1+now-1)/16]^b2[(p2+now-1)%16][(p2+now-1)/16]]; for(;now<=len;now++) res+=S1[p1+now-1]^S2[p2+now-1]; return res; } const double PI=acos(-1); struct E{ double real,imag; E(double t1=0,double t2=0){ real=t1; imag=t2; } void operator /= (const int &val){ real/=val; imag/=val; } }; E operator + (const E &A,const E &B){ return E(A.real+B.real,A.imag+B.imag); } E operator - (const E &A,const E &B){ return E(A.real-B.real,A.imag-B.imag); } E operator * (const E &A,const E &B){ return E(A.real*B.real-A.imag*B.imag,A.imag*B.real+A.real*B.imag); } E operator / (const E &A,const int &x){ return E(A.real/x,A.imag/x); } int rev[maxn]; void get_rev(int n){ rev[0]=0; int log2n=log2(n); for(int i=1;i<=n-1;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(log2n-1)); } void FFT(E a[],int n,int _k){ for(int i=0;i<=n-1;i++) if (i<rev[i]) swap(a[i],a[rev[i]]); for(int m=2;m<=n;m<<=1){ E wm(cos(2*PI/m),_k*sin(2*PI/m)); for(int k=0;k<=n-1;k+=m){ E w(1,0),t0,t1; for(int j=0;j<=m/2-1;j++,w=w*wm) t0=a[k+j], t1=w*a[k+j+m/2], a[k+j]=t0+t1, a[k+j+m/2]=t0-t1; } } if(_k==-1) for(int i=0;i<=n-1;i++) a[i]/=n; } E _S1[maxn],_S2[maxn],F[maxn]; int main(){ freopen("hhhoj42.in","r",stdin); freopen("hhhoj42.out","w",stdout); char ch=gc(); while(ch!='0'&&ch!='1') ch=gc(); for(int i=0;ch=='0'||ch=='1';ch=gc(),i++) S1[i]=ch-'0', n++; ch=gc(); while(ch!='0'&&ch!='1') ch=gc(); for(int i=0;ch=='0'||ch=='1';ch=gc(),i++) S2[i]=ch-'0', m++; if(n>=300000){ for(int i=0;i<=n-1;i++) sum1+=S1[i]*S1[i]; for(int i=0;i<=m-1;i++) sum2[i]=(i-1>=0?sum2[i-1]:0)+S2[i]*S2[i]; for(int i=0;i<=n-1;i++) _S1[i]=S1[i]; for(int i=0;i<=m-1;i++) _S2[i]=S2[i]; for(int i=0;i<=(n-1)/2;i++) swap(_S1[i],_S1[n-1-i]); int _m=1; while(_m<m) _m<<=1; get_rev(_m); FFT(_S1,_m,1); FFT(_S2,_m,1); for(int i=0;i<=_m-1;i++) F[i]=_S1[i]*_S2[i]; FFT(F,_m,-1); Q=getint(); while(Q--){ int p1=getint(),p2=getint(),len=getint(); p2=(p2^last_ans)%(m-len+1); int res=(F[p2+n-1].real+0.1); printf("%d\n",last_ans=sum1+sum2[p2+n-1]-(p2-1>=0?sum2[p2-1]:0)-2*res); } return 0; } Pre(); Q=getint(); while(Q--){ int p1=getint(),p2=getint(),len=getint(); p2=(p2^last_ans)%(m-len+1); printf("%d\n",last_ans=Solve(p1,p2,len)); } return 0; }
相关文章推荐
- [FFT 压位] Hillan模拟赛 A.简单字符串匹配
- Blue Jeans(poj3080简单字符串匹配)
- HDU3065(病毒侵袭持续中)字符串匹配-简单的AC自动机
- BZOJ4259:残缺的字符串(FFT与字符串匹配)
- POJ 1035 Spell checker 简单字符串匹配
- C#正则表达式进行简单的字符串匹配识别
- 简单字符串匹配问题-——用哈希解决
- 字符串匹配算法——KMP算法简单解释
- KMP字符串匹配 简单理解
- 字符串匹配——简单匹配,KMP,分析讲解
- 简单字符串匹配方法
- 第3次CCF-3-字符串匹配(kmp的简单应用)
- 简单的字符串匹配 poj1936
- 字符串匹配的KMP算法(简单清晰的认识KMP)
- P3375 【模板】KMP字符串匹配(全程注释,简单易懂)
- Python做简单的字符串匹配详解
- php 类似正则获取字符串匹配内容的简单方法
- 几种字符串匹配算法性能简单实验对比
- poj 1936 All in All 简单的字符串匹配
- 简单字符串匹配