bzoj1014: [JSOI2008]火星人prefix

我TM的怕不是个傻逼。。check里面比较hash搞成比较c,居然还能过数据,还过了n个对拍。。果然假如考试信样例就有鬼了。

嗯隔壁哈老师告诉我,hash其实不用mod,直接自然溢出就行,get到新姿势。

这道题前两个操作明显可以用伸展树来解决,问题在于比较两个后缀的前缀,那我们的做法就是令伸展树记录一个h表示当前子树的hash,那我们通过比较hash就可以方便的知道,两个子串是否相等,那比较后缀时,就用二分枚举匹配长度,然后比较hash就行了、

#include<cstdio>
#include<cstring>
using namespace std;
int mi[110000];
struct node
{
    int f,c,h,hash,son[2];//hash表示以当前节点管理的节点的hash值 
}tr[110000];int root,len;
void update(int x)
{
    int lc=tr[x].son[0],rc=tr[x].son[1];
    tr[x].c=tr[lc].c+tr[rc].c+1;
    tr[x].hash=tr[lc].hash*mi[tr[rc].c+1] + tr[x].h*mi[tr[rc].c] + tr[rc].hash;
}
void rotate(int x,int w)
{
    int f=tr[x].f,ff=tr[f].f;
    int r,R;
    
    r=tr[x].son[w];R=f;
    tr[R].son[1-w]=r;
    if(r!=0)tr[r].f=R;
    
    r=x;R=ff;
    if(tr[ff].son[0]==f)tr[R].son[0]=r;
    else                 tr[R].son[1]=r;
    tr[r].f=R;
    
    r=f;R=x;
    tr[R].son[w]=r;
    tr[r].f=R;
    
    update(f);
    update(x);
}
void splay(int x,int rt)
{
    while(tr[x].f!=rt)
    {
        int f=tr[x].f,ff=tr[f].f;
        if(ff==rt)
        {
            if(x==tr[f].son[0])rotate(x,1);
            else                rotate(x,0);
        }
        else
        {
                 if(tr[f].son[0]==x&&tr[ff].son[0]==f){rotate(f,1);rotate(x,1);}
            else if(tr[f].son[1]==x&&tr[ff].son[0]==f){rotate(x,0);rotate(x,1);}
            else if(tr[f].son[0]==x&&tr[ff].son[1]==f){rotate(x,1);rotate(x,0);}
            else if(tr[f].son[1]==x&&tr[ff].son[1]==f){rotate(f,0);rotate(x,0);}
        }
    }
    if(rt==0)root=x;
}
void ins(int h,int f)
{
    len++;
    tr[len].c=1;tr[len].h=h;
    tr[len].hash=h;
    tr[len].son[0]=tr[len].son[1]=0;
    
    if(f==0){tr[len].f=0;root=len;}
    else
    {
        splay(f,0);
        if(tr[f].son[1]==0)
        {
            tr[len].f=f;
            tr[f].son[1]=len;
        }
        else
        {
            f=tr[f].son[1];
            while(tr[f].son[0]!=0)f=tr[f].son[0];
            
            tr[len].f=f;
            tr[f].son[0]=len;
        }
        splay(f,0);
    }
}
int findweizhi(int k)
{
    int x=root;
    while(x!=0)
    {
        int d=tr[tr[x].son[0]].c+1;
             if(k<d) x=tr[x].son[0];
        else if(d<k){x=tr[x].son[1];k-=d;}
        else break;
    }
    return x;
}
void change(int x,int h)
{
    splay(x,0);
    tr[x].h=h;
    update(x);
}
bool check(int x,int y,int mid)
{
    int xl=findweizhi(x),xr=findweizhi(x+mid-1);
    int yl=findweizhi(y),yr=findweizhi(y+mid-1);
    
    if(tr[xl].h!=tr[yl].h||tr[xr].h!=tr[yr].h)return false;
    
    if(mid<=2)return true;

    int hx,hy;
    
    splay(xl,0);splay(xr,xl);
    hx=tr[tr[xr].son[0]].hash;
    
    splay(yl,0);splay(yr,yl);
    hy=tr[tr[yr].son[0]].hash;
    
    if(hx==hy)return true;
    return false;
}
char ss[110000];
int main()
{
    freopen("hehe.in","r",stdin);
    freopen("w.out","w",stdout);
    mi[0]=1;for(int i=1;i<=100000;i++)mi[i]=mi[i-1]*27;
    root=len=0;ins(0,0);
    scanf("%s",ss+1);int slen=strlen(ss+1);
    for(int i=1;i<=slen;i++)ins(int(ss[i]-'a'+1),len);
    
    int m,x,y;
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",ss+1);
        if(ss[1]=='R')
        {
            scanf("%d%s",&x,ss+1);
            x=findweizhi(x+1);
            change(x,int(ss[1]-'a'+1));
        }
        else if(ss[1]=='I')
        {
            scanf("%d%s",&x,ss+1);
            x=findweizhi(x+1);
            ins(int(ss[1]-'a'+1),x);
        }
        else
        {
            scanf("%d%d",&x,&y);x++;y++;
            if(x>y){int t=x;x=y;y=t;}
            
            int l=1,r=len-y+1,ans=0;
            while(l<=r)
            {
                int mid=(l+r)/2;
                if(check(x,y,mid)==true)
                {
                    l=mid+1;
                    ans=mid;
                }
                else r=mid-1;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

 

posted @ 2017-10-09 11:01  AKCqhzdy  阅读(195)  评论(0编辑  收藏  举报