您的位置:首页 > 其它

[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: