BZOJ2555: SubString

这题写得我真想吐...

主要注意一个地方。

1.每次cut的时候,cut的一颗子树,而不是只有q这个节点。

说到底,还是没有对fail树的形态有一个清晰地认识,不过这道题写后就好很多。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define mem1(i,j) memset(i,j,sizeof(i))
#define mem2(i,j) memcpy(i,j,sizeof(i))
#define LL long long
#define up(i,j,n) for(int i=(j);i<=(n);i++)
#define FILE "dealing"
#define poi vec
#define eps 1e-10
#define db double
const int maxn=1620000,inf=1000000000,mod=1000000007;
int read(){
    int x=0,f=1,ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0',ch=getchar();}
    return f*x;
}
bool cmax(int& a,int b){return a<b?a=b,true:false;}
bool cmin(int& a,int b){return a>b?a=b,true:false;}
string s;char ch[maxn];int mask=0;
namespace LCT{
    int c[maxn][2],fa[maxn],val[maxn],siz[maxn],rev[maxn],delet[maxn];
    bool isroot(int x){if(!x)return 1;return c[fa[x]][1]!=x&&c[fa[x]][0]!=x;}
    //void revv(int x){if(!x)return;swap(c[x][0],c[x][1]);rev[x]^=1;}
    void add(int x,int d){if(!x)return;delet[x]+=d;val[x]+=d;}
    void pushdown(int x){
        if(!x)return;
        //if(rev[x]){rev[x]^=1;revv(c[x][1]);revv(c[x][0]);}
        if(delet[x])add(c[x][1],delet[x]),add(c[x][0],delet[x]),delet[x]=0;
    }
    void rotate(int x){
        if(!x)return;
        int y=fa[x],z=fa[y],d=c[y][1]==x;
        if(!isroot(y))c[z][c[z][1]==y]=x;
        fa[y]=x;fa[x]=z;if(c[x][d^1])fa[c[x][d^1]]=y;
        c[y][d]=c[x][d^1];c[x][d^1]=y;
    }
    int q[maxn],top=0;
    void splay(int x){
        q[++top]=x;
        for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
        while(top)pushdown(q[top--]);
        while(!isroot(x)){
            int y=fa[x],z=fa[y];
            if(!isroot(y)){
                if(c[y][1]==x^c[z][1]==y)rotate(x);
                else rotate(y);
            }
            rotate(x);
        }
    }
    void access(int x){for(int t=0;x;t=x,x=fa[x])splay(x),c[x][1]=t;}
    void cut(int x){
        access(x);splay(x);
        add(c[x][0],-val[x]);
        c[x][0]=fa[c[x][0]]=0;
    }
    void link(int x,int y){
        access(y);splay(y);fa[x]=y;
        add(y,val[x]);
    }
};
namespace SAM{
    int c[maxn][26],pre[maxn],len[maxn],cnt=1,now=1,Now=1;
    void extend(int x){
        int nq,np,q,p;
        p=Now;Now=np=++cnt;len[np]=len[p]+1;LCT::val[np]++;
        while(p&&!c[p][x])c[p][x]=np,p=pre[p];
        if(!p){pre[np]=1;
            LCT::link(np,1);
        }
        else {
            q=c[p][x];
            if(len[q]==len[p]+1)pre[np]=q,LCT::link(np,q);
            else {
                len[nq=++cnt]=len[p]+1;
                mem2(c[nq],c[q]);
                pre[nq]=pre[q];
                 
                LCT::link(nq,pre[q]);
                LCT::cut(q);
                LCT::link(q,nq);
                LCT::link(np,nq);
                 
                pre[q]=pre[np]=nq;
                while(p&&c[p][x]==q)c[p][x]=nq,p=pre[p];
            }
        }
    }
    int Len=0;
    void prepare(){Len=0,now=1;}
    int walk(int x){
        while(pre[now]&&!c[now][x])now=pre[now],Len=len[now];
        if(!c[now][x])return 0;
        now=c[now][x];Len++;return Len;
    }
    int solve(){
        LCT::access(now);LCT::splay(now);return LCT::val[now];
    }
    void build(char* s){
        int n=strlen(s+1);Now=1,cnt=1;
        up(i,1,n)extend(s[i]-'A');
    }
};
void load(int mask){
    scanf("%s",ch);
    s=ch;
    up(j,0,s.length()-1){
        mask=(mask*131+j)%s.length();
        char t=s[j];
        s[j]=s[mask];
        s[mask]=t;
    }
}
int main(){
    //freopen(FILE".in","r",stdin);
    //freopen(FILE".out","w",stdout);
    int Q=read();
    scanf("%s",ch+1);
    SAM::build(ch);
    while(Q--){
        scanf("%s",ch+1);
        if(ch[1]=='Q'){
            load(mask);
            //cin>>s;
            SAM::prepare();int n=s.length(),m;
            up(i,0,n-1)m=SAM::walk(s[i]-'A');
            int ans=(m==n?SAM::solve():0);
            mask^=ans;
            printf("%d\n",ans);
        }
        else {
            load(mask);
            //cin>>s;
            int n=s.length();
            up(i,0,n-1)SAM::extend(s[i]-'A');
        }
    }
    return 0;
}

  

posted @ 2017-02-21 20:21  CHADLZX  阅读(116)  评论(0编辑  收藏  举报