hdu4787 在线ac自动机

来源:互联网 发布:你难忘的事情 知乎 编辑:程序博客网 时间:2024/06/05 01:19

2013 成都赛区 G题

有点难度阿..

题目看错调了两天


通过这题  我了解了何为在线ac自动机

做过的 ac自动机题都是先给好模板串  再给目标串

这样getfail就是遍历一遍节点  就行


于是想到那就每次询问之前都getfail一次吧!

结果TLE..


于是只能看题解..

额..什么叫在线ac自动机?

好吧..在线ac自动机也是每询问一次就getfail一次

那怎么省时间呢?

getfail的时间复杂度就是节点数  那么就减少getfail的节点----开两棵树

一棵小树做缓存buf  每次都对她getfail  大树做堆heap

当小树的size(诶嘿)达到一个数值后就放进 大树就吃了小树(append(), -  -)并getfail

询问时同时问大树和小树  求和





#include <stdio.h>#include <string.h>#define ff(i,n) for(int i=0;i<n;i++)const int CH = 2,NODE = 100005;int idx(char x){    return x-'0';}int queue[NODE];struct DFA{    int ch[NODE][CH],f[NODE],val[NODE],last[NODE],sz;    void init()    {        sz=1;        memset(ch[0],0,sizeof(ch[0]));    }    void nn(int u,int c)    {        memset(ch[sz],0,sizeof(ch[sz]));        val[sz]=0;        ch[u][c]=sz++;    }    void ins(char *s)    {        int u=0;        for(;*s;s++)        {            int c=idx(*s);            if(!ch[u][c])                nn(u,c);            u=ch[u][c];        }        val[u]=1;    }    void getfail()    {        int *rear=queue,*front=queue;        ff(c,CH)        {            int u=ch[0][c];            if(u)                f[u]=0,last[u]=0,*rear++=u;        }        while(rear!=front)        {            int cur = *front++;            ff(c,CH)            {                int u=ch[cur][c];                int fail=f[cur];                if(u)                {                    while(fail && !ch[fail][c]) fail = f[fail];                    f[u]=ch[fail][c];                    last[u]=val[f[u]]?f[u]:last[f[u]];                    *rear++=u;                }            }        }    }    int calc(char *s)    {        int sum=0;        int u=0;        for(;*s;s++)        {            int c=idx(*s);            while(u&&!ch[u][c]) u=f[u];            u=ch[u][c];            for(int tmp=u;tmp;tmp=last[tmp])                sum+=val[tmp];        }        //puts("");        return sum;    }    int search(char *s)    {        int u=0;        for(; *s; s++)        {            int c=idx(*s);            if(!ch[u][c])                return 0;            u=ch[u][c];        }        return val[u];    }}heap,buf;void append(int uh,int ub){    heap.val[uh]+=buf.val[ub];    ff(c,CH)    {        int nh=heap.ch[uh][c];        int nb=buf.ch[ub][c];        if(nb)        {            if(!nh)            {                heap.nn(uh,c);                nh=heap.ch[uh][c];            }            append(nh,nb);        }    }}void join(){    append(0,0);    buf.init();    heap.getfail();}char s[10000005];void move(int n){    //printf("->>%d\n",n);    if(!n) return;    int len=strlen(s);    n%=len;    for(int i=0;i<n;i++)        s[i+len] = s[i];    s[n+len]=0;    strcpy(s,s+n);    s[len]=0;}int main(){    int T,cas=1;    scanf("%d",&T);    while(T--)    {        printf("Case #%d:\n",cas++);        heap.init();        buf.init();        char cmd;        int n,flag=0,sft=0;;        scanf("%d",&n);        while(n--)        {            getchar();            scanf("%c",&cmd);            scanf("%s",s);            move(sft);            if(cmd=='+')            {                if(buf.search(s)||heap.search(s)) continue;                flag++;                buf.ins(s);                if(buf.sz>2000)                    join(),flag=0;            }            else            {                if(flag)                    buf.getfail();                sft=heap.calc(s)+buf.calc(s);                printf("%d\n",sft);            }        }    }    return 0;}


0 0
原创粉丝点击