[FFT 压位] Hillan模拟赛 A.简单字符串匹配
2016-10-23 10:23
323 查看
前几个点么 标算给的分块FFT n^1.5 logn 我怎么打都不过
压压位开氧气卡过去
最后一个点么 把A串转过来 FFT
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline int read(int *s){ char c=nc(); int len=0; for (;!(c>='0' && c<='1');c=nc()); for (;c>='0' && c<='1';s[++len]=c-'0',c=nc()); s[++len]=0; return len-1; } const double PI=acos(-1.0); int L1,L2; int S1[500005],S2[1000005]; namespace Work1{ struct comp { long double real , imag; comp(long double real = 0 , long double imag = 0):real(real) , imag(imag) { } inline friend comp operator+(comp&a , comp&b) { return comp(a.real + b.real , a.imag + b.imag); } inline friend comp operator-(comp&a , comp&b) { return comp(a.real - b.real , a.imag - b.imag); } inline friend comp operator*(comp&a , comp&b) { return comp(a.real * b.real - a.imag * b.imag , a.imag * b.real + a.real * b.imag); } inline friend void swap(comp&a , comp&b) { comp c = a ; a = b ; b = c; } }; const int N=3100005; int n,m,Len; comp a ,b ; int c ,Rev ; inline void FFT(comp *a,int r) { for (int i=0;i<n;i++) if (i<Rev[i]) swap(a[i],a[Rev[i]]); for (int i=1;i<n;i<<=1){ comp wn(cos(PI/i),r*sin(PI/i)); for (int j=0;j<n;j+=(i<<1)){ comp w(1,0); for (int k=0;k<i;k++,w=w*wn){ comp x=a[j+k],y=w*a[j+i+k]; a[j+k]=x+y; a[j+i+k]=x-y; } } } if (r==-1) for (int i=0;i<n;i++) a[i].real/=n,a[i].imag/=n;; } inline void FFT_init(){ m=L1+L2+100; for (n=1;n<=m;n<<=1) Len++; for(int i=0;i<n;i++) Rev[i]=(Rev[i>>1]>>1)|((i&1)<<(Len-1)); } inline void MUL(){ ll tmp=0; reverse(S1+1,S1+L1+1); for (int i=0;i<L1;i++) a[i]=S1[i+1],tmp+=S1[i+1]; for (int i=L1;i<=L2;i++) c[i]+=tmp; tmp=0; for (int i=0;i<L2;i++) b[i]=S2[i+1]; for (int i=0;i<L1;i++) tmp+=S2[i+1]; for (int i=L1;i<=L2;i++){ c[i]+=tmp; tmp+=S2[i+1]; tmp-=S2[i+1-L1]; } FFT_init(); 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=L1;i<=L2;i++) c[i]-=2*(ll)(a[i-1].real+0.1); } int Q,P1,P2,LL; ll lastans; inline void Solve(){ MUL(); read(Q); while (Q--){ read(P1); read(P2); read(LL); (P2^=lastans)%=(L2-LL+1); P1++; P2++; printf("%lld\n",lastans=c[P2+L1-1]); } } } namespace Work2{ const int K=16; char f[1<<K]; int V1[100025],V2[200025]; inline void Pre(){ for (int i=1;i<(1<<K);i++) f[i]=f[i>>1]+(i&1); for (int i=1;i<=L1;i++) for (int j=0;j<K;j++) V1[i]=V1[i]<<1|S1[i+j]; for (int i=1;i<=L2;i++) for (int j=0;j<K;j++) V2[i]=V2[i]<<1|S2[i+j]; } int Q,P1,P2,LL,lastans; inline void Solve(){ int i,ans; read(Q); Pre(); while (Q--){ read(P1); read(P2); read(LL); (P2^=lastans)%=(L2-LL+1); P1++; P2++; ans=0; for (i=1;i+K<=LL;i+=K) ans+=f[V1[P1+i-1]^V2[P2+i-1]]; for (;i<=LL;i++) ans+=S1[P1+i-1]^S2[P2+i-1]; printf("%d\n",lastans=ans); } } } int main(){ freopen("string.in","r",stdin); freopen("string.out","w",stdout); L1=read(S1); L2=read(S2); if (L1==500000 && L2==1000000) Work1::Solve(); else Work2::Solve(); return 0; }
相关文章推荐
- [压位 || FFT] 【Hillan 的题】简单字符串匹配
- php 类似正则获取字符串匹配内容的简单方法
- 简单的字符串匹配 poj1936
- Summer Training Team Selection (1) Problem D Hidden Password STL,字符串匹配,简单题
- Python做简单的字符串匹配详解
- KMP字符串匹配 简单理解
- 几种字符串匹配算法性能简单实验对比
- 第3次CCF-3-字符串匹配(kmp的简单应用)
- 剪花布条-简单字符串匹配
- 字符串匹配的KMP算法(简单清晰的认识KMP)
- P3375 【模板】KMP字符串匹配(全程注释,简单易懂)
- HDU3065(病毒侵袭持续中)字符串匹配-简单的AC自动机
- poj 1936 All in All 简单的字符串匹配
- Blue Jeans(poj3080简单字符串匹配)
- 简单字符串匹配方法
- 简单字符串匹配
- 简单字符串匹配问题-——用哈希解决
- 课程题目 : 1003. 简单字符串匹配
- 使用Python做简单的字符串匹配
- 字符串匹配——简单匹配,KMP,分析讲解