HDU4270 Dynamic Lover(后缀自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4270

题意:给出一个串s,有三种操作:(1)将一个串t接在s之后;(2)给出len,输出不大于len的后缀和长度为len的子串中字典序最小的;(3)给出len,删掉长度为len的后缀。

思路:建立s的后缀自动机。(1)直接将t插入;(2)从last向前,标记所有的终结点。然后从head开始DFS;(3)将所有删去的节点以及以复制得到的节点标记删去,方法是共同指向一个标记。





const int KIND=26;

struct SAM

{

    SAM *son[KIND],*pre;

    int len,cnt,flag,id,*isDel;



    void init()

    {

        clr(son,NULL);

        pre=NULL;

        id=flag=len=0;

    }

};



SAM sam[N],*head,*last;

int cnt,len;

char s[N];

int isDel[N],delCnt,posMap[N];



void initSAM()

{

    sam[0].init();

    head=last=&sam[0];

    isDel[delCnt]=0;

    head->isDel=&isDel[delCnt++];

    cnt=1;

}





void insert(int x)

{

    SAM *p=&sam[cnt],*u=last;

    p->init();

    p->len=p->id=last->len+1;

    posMap[p->len]=cnt++;



    isDel[delCnt]=0;

    p->isDel=&isDel[delCnt++];

    last=p;

    

    for(;u&&(!u->son[x]||*u->son[x]->isDel);u=u->pre) u->son[x]=p;

    if(!u) p->pre=head;

    else if(u->son[x]->len==u->len+1) p->pre=u->son[x];

    else

    {

        SAM *r=&sam[cnt++],*q=u->son[x];

        *r=*q; r->len=u->len+1;

        p->pre=q->pre=r;

        for(;u&&u->son[x]==q;u=u->pre) u->son[x]=r;

    }

}





void insert()

{

    RD(s);

    int L=strlen(s),i;

    FOR0(i,L) insert(s[i]-'a'),len++;

}



int dep,flag;



int DFS(SAM *p,int _dep)

{

    if(_dep==dep) return p->id-_dep+1;

    if(p->flag==flag) return len-_dep+1;

    int i;

    FOR0(i,26) if(p->son[i]&&!(*p->son[i]->isDel))

    {

        return DFS(p->son[i],_dep+1);

    }

}



void find()

{

    flag++;

    SAM *p=last;

    while(p&&p!=head) p->flag=flag,p=p->pre;

    head->flag=0;

    RD(dep);

    PR(DFS(head,0));

}







void del()

{

    int L;

    RD(L);

    int i;

    FOR(i,len-L+1,len) *sam[posMap[i]].isDel=1;

    len-=L;

    last=&sam[posMap[len]];

}



int main()

{

    while(scanf("%s",s)!=-1)

    {

        delCnt=0;

        initSAM(); len=strlen(s);

        int i;

        FOR0(i,len) insert(s[i]-'a');

        int Q,op;

        RD(Q);

        while(Q--)

        {

            RD(op);

            if(op==1) insert();

            else if(op==2) find();

            else del();

        }

    }

    return 0;

}

  

你可能感兴趣的:(dynamic)