zoukankan      html  css  js  c++  java
  • 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
    ",ans);
            }
            else {
                load(mask);
                //cin>>s;
                int n=s.length();
                up(i,0,n-1)SAM::extend(s[i]-'A');
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    目前博客园NB团队成员名单
    [征询意见]博客园准备组建在线培训团队
    [调查]园子里有哪些朋友在做开源项目
    都是百度惹的祸
    准备成立NBear开源项目团队—博客园NB团队
    [公告]欢迎各地.NET俱乐部负责人与我联系
    [公告]服务器搬迁
    VS 2005 文本编码小技巧
    Net Framework 2.0 事务处理
    ArgoUML 开源UML 建模工具
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6426028.html
Copyright © 2011-2022 走看看