bzoj 2555 Substring

SAM的下标我一直都是从0开始,结果带入LCT就挂了,而且蜜汁MLE,找了好久才发现,交了好多遍

/**************************************************************
    Problem: 2555
    User: Clare
    Language: C++
    Result: Accepted
    Time:15276 ms
    Memory:161280 kb
****************************************************************/
 
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
 
#define N 1200010
 
int n,m,Mask;
char S[3000010],op[10];
 
struct LCT{
    int fa[N],c[N][2],flag[N],v[N];
    stack<int> st;
    bool Pd_root(int k)
    {
        return !(c[fa[k]][0]==k)&&!(c[fa[k]][1]==k);
    }
    void Pushdown(int k)
    {
        int l=c[k][0],r=c[k][1];
        if(flag[k]!=0)
        {
            flag[l]+=flag[k];flag[r]+=flag[k];
            v[l]+=flag[k];v[r]+=flag[k];
            flag[k]=0;
        }
    }
    void Rotate(int x)
    {
        int y=fa[x],z=fa[y],l,r;
        if(c[y][0]==x)l=0;else l=1;
        r=l^1;
        if(Pd_root(y));
        else c[z][c[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
    }
    void Splay(int x)
    {
        st.push(x);
        for(int i=x;!Pd_root(i);i=fa[i])
            st.push(fa[i]);
        while(!st.empty())
        {
            int now=st.top();st.pop();
            Pushdown(now);
        }
        while(!Pd_root(x))
        {
            int y=fa[x],z=fa[y];
            if(!Pd_root(y))
            {
                if(c[y][0]==x^c[z][0]==y)
                    Rotate(x);
                else Rotate(y);
            }
            Rotate(x);
        }
    }
    void Access(int x)
    {
        for(int i=0;x;i=x,x=fa[x])
            Splay(x),c[x][1]=i;
    }
    void Move_to_root(int x)
    {
        Access(x);Splay(x);
    }
    void Join(int x,int y)
    {
        fa[x]=y;Move_to_root(y);
        flag[y]+=v[x];
        v[y]+=v[x];
    }
    void Cut(int x)
    {
        Move_to_root(x);
        flag[c[x][0]]-=v[x];v[c[x][0]]-=v[x];
        fa[c[x][0]]=0;c[x][0]=0;
    }
}t;
 
struct SAM{
    int fa[N],son[N][26];
    int val[N];
    int tot,root,last,p,np,q,nq;
    void Init()
    {
        tot=0;last=root=++tot;
    }
    void Insert(int w)
    {
        p=last,np=++tot;val[np]=val[p]+1;
        t.v[np]=1;
        while(p&&!son[p][w])
            son[p][w]=np,p=fa[p];
        if(!p)
            fa[np]=root,t.Join(np,root);
        else
        {
            q=son[p][w];
            if(val[q]==val[p]+1)
                fa[np]=q,t.Join(np,q);
            else
            {
                nq=++tot;val[nq]=val[p]+1;
                memcpy(son[nq],son[q],sizeof(son[q]));
                fa[nq]=fa[q];t.Join(nq,fa[q]);
                fa[q]=fa[np]=nq;t.Cut(q);t.Join(q,nq);t.Join(np,nq);
                while(p&&son[p][w]==q)
                    son[p][w]=nq,p=fa[p];
            }
        }
        last=np;
    }
    void Change_mask(char *str,int mask)
    {
        int len=(int)strlen(str);
        for(int i=0;i<len;i++)
        {
            mask=(mask*131+i)%len;
            char t=str[i];
            str[i]=str[mask];
            str[mask]=t;
        }
    }
    void Get_in(char *str)
    {
        Change_mask(str,Mask);
        int len=(int)strlen(str);
        for(int i=0;i<len;i++)
            Insert(str[i]-'A');
    }
    int Query(char *str)
    {
        Change_mask(str,Mask);
        int len=(int)strlen(str),now=root;
        for(int i=0;i<len;i++)
            if(son[now][str[i]-'A'])
                now=son[now][str[i]-'A'];
            else return 0;
        t.Splay(now);
        return t.v[now];
    }
}A;
 
int main()
{
    int Q;scanf("%d",&Q);
    A.Init();
    scanf("%s",S);
    int len=(int)strlen(S);
    for(int i=0;i<len;i++)
        A.Insert(S[i]-'A');
    while(Q--)
    {
        scanf("%s",op);scanf("%s",S);
        if(op[0]=='A')
            A.Get_in(S);
        else
        {
            int Ans=A.Query(S);
            printf("%d\n",Ans);
            Mask^=Ans;
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值