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

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

还好不卡。。。

因为要半路加点所以可以想到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 100005
int 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;
}


你可能感兴趣的:(splay,字符串hash)