【BZOJ1014】火星人prefix Splay 字符串Hash

来源:互联网 发布:用友软件的功能 编辑:程序博客网 时间:2024/05/17 09:36

这道题要是卡自然溢出还真的有点慢。。。

还好不卡。。。

因为要半路加点所以可以想到Splay,针对每一个询问操作,我们二分一个答案出来,在Splay将这两段单独隔离出来检查Hash值是否相同,所以插入的时间复杂度是logn,查询是log^2n,满足题目的要求

/**************************************************************    Problem: 1014    User: RicardoWang    Language: C++    Result: Accepted    Time:6912 ms    Memory:4888 kb****************************************************************/ #include<cstdlib>#include<cstdio>#include<iostream>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<queue>using namespace std;#define maxl 100005#define maxa 100005int sz[maxa],chi[maxa][2],cc[maxa],f[maxa],np,rt;unsigned long long w[maxa],_power[100005],pow_num=29;void _read(int &x){    char ch=getchar();    while(ch<'0' || ch>'9')    {        ch=getchar();    }    x=0;    while(ch>='0' && ch<='9')    {        x=x*10+ch-'0';        ch=getchar();    }    return ;}void push_up(int now){    sz[now]=1;w[now]=0;    if(chi[now][1])    {        sz[now]+=sz[chi[now][1]];        w[now]=w[chi[now][1]];    }    w[now]=w[now]*pow_num+cc[now];    if(chi[now][0])    {        sz[now]+=sz[chi[now][0]];        w[now]=w[chi[now][0]]+w[now]*_power[sz[chi[now][0]]];    }    return ;}void Link(int i,int d,int j){    chi[i][d]=j;    f[j]=i;    return ;}void rot(int x){    int y=f[x];int z=f[y];    if(!y)return ;    int d=(chi[y][0]==x);    Link(y,d^1,chi[x][d]);    Link(z,chi[z][1]==y,x);    Link(x,d,y);    push_up(y);push_up(x);    return ;}void Splay(int &now,int x,int anc){    int y,z;    while(f[x]!=anc)    {        y=f[x]; z=f[y];        if(z!=anc)        {            if((chi[z][1]==y)==(chi[y][1]==x))            {                rot(y);            }            else            {                rot(x);            }        }        rot(x);    }    if(anc==0)    {        now=x;    }    return ;}int Kth(int &now,int k,int anc){    int t,ct=0,p=now;    while(p)    {        t=sz[chi[p][0]]+1;        if(ct+t==k)        {            break;        }        else if(ct+t<k)        {            ct+=t;            p=chi[p][1];        }        else        {            p=chi[p][0];        }    }    if(p)Splay(now,p,anc);    return p;}void update(int x,int c){    int p=Kth(rt,x,0);    cc[p]=c;    push_up(p);    return ;}void Insert(int x,int c){    int p=Kth(rt,x,0);    int q=Kth(rt,x+1,p);    np++; w[np]=cc[np]=c;sz[np]=1;    Link(q,0,np);    push_up(q);    push_up(p);    return ;}unsigned gethash(int x,int y){    int p=Kth(rt,x-1,0);    int q=Kth(rt,y+1,p);    return w[chi[q][0]];}void query(int x,int y){    int l=0,r=min(np-x,np-y),mid,ans=0;    unsigned long long t1,t2;    while(l<=r)    {        mid=(l+r)>>1;        t1=gethash(x,x+mid-1);        t2=gethash(y,y+mid-1);        if(t1==t2)        {            ans=mid;            l=mid+1;        }        else        {            r=mid-1;        }    }    printf("%d\n",ans);    return ;}void ready(){    np=2; rt=1;    f[1]=0;    sz[1]=2; sz[2]=0; cc[1]=cc[2]=0;    Link(1,1,2);    return ;}char s0[maxl]; void Init(){    scanf("%s",s0);//  fprintf(stderr,"%s\n",s0);    int l=strlen(s0);    ready();     for(int i=0;i<l;i++)    {        Insert(i+1,s0[i]-'a');        Splay(rt,np,0);     }    return ;}int m;void work(){    scanf("%d",&m);//  if(m>100)return ;//  fprintf(stderr,"%d\n",m);    char op,col;    int x,y;    for(int i=1;i<=m;i++)    {        op=getchar();        while(op!='Q' && op!='R' && op!='I')        {            op=getchar();        }        if(op=='Q')        {            _read(x); _read(y);        //  fprintf(stderr,"%c %d %d\n",op,x,y);            x++; y++;            query(x,y);        }        else if(op=='R')        {            _read(x);            x++;            col=getchar();            while(col<'a' || col>'z')            {                col=getchar();            }        //  fprintf(stderr,"%c %d %c\n",op,x-1,col);            update(x,col-'a');        }        else        {            _read(x);            x++;            col=getchar();            while(col<'a' || col>'z')            {                col=getchar();            }        //  fprintf(stderr,"%c %d %c\n",op,x-1,col);            Insert(x,col-'a');        }    }}int main(){    //freopen("in.txt","r",stdin);    _power[0]=1;    for(int i=1;i<=100000;i++)    {        _power[i]=_power[i-1]*pow_num;    }    Init();    work();    return 0;}


0 0
原创粉丝点击