ZOJ 3228 Searching the String(自动机)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3441

题意:给定一个串s以及N个子串,问每个子串在s中出现的次数。有些子串允许在s中有重叠有些不允许。

思路:自动机:每个节点记录到达次数,type为1时记录前一次到达时是啥时候。







const int N=200005;



struct node

{

    int next[26],fail,cnt[2],pre,len;



    void init()

    {

        clr(next,-1);

        fail=-1;

        cnt[0]=cnt[1]=0;

        pre=-1;

        len=0;

    }

};



node a[N];

int e,n,*mp[N];





void insert(char s[],int t,int id)

{

    int i,k,p=0;

    for(i=0;s[i];i++)

    {

        k=s[i]-'a';

        if(a[p].next[k]==-1)

        {

            a[e].init();

            a[p].next[k]=e++;

        }

        p=a[p].next[k];

    }

    a[p].len=i;

    mp[id]=&(a[p].cnt[t]);

}





void build()

{

    queue<int> Q;

    int i,j,k,t,p,q;

    Q.push(0);

    while(!Q.empty())

    {

        k=Q.front();

        Q.pop();



        for(i=0;i<26;i++)

        {

            if(a[k].next[i]!=-1)

            {

                p=a[k].next[i];

                q=a[k].fail;

                while(q!=-1&&a[q].next[i]==-1) q=a[q].fail;

                if(q==-1) a[p].fail=0;

                else a[p].fail=a[q].next[i];

                Q.push(p);

            }

            else

            {

                q=a[k].fail;

                while(q!=-1&&a[q].next[i]==-1) q=a[q].fail;

                if(q==-1) a[k].next[i]=0;

                else a[k].next[i]=a[q].next[i];

            }

        }

    }

}



char s[N];





void find(char s[])

{

    int p=0,i,j,k,t;

    for(i=0;s[i];i++)

    {

        k=s[i]-'a';

        p=a[p].next[k];

        t=p;

        while(t!=-1)

        {

            if(a[t].len>0)

            {

                a[t].cnt[0]++;

                if(a[t].pre==-1||i-a[t].pre>=a[t].len)

                {

                    a[t].cnt[1]++;

                    a[t].pre=i;

                }

            }

            t=a[t].fail;

        }

    }

}



int main()

{

    int num=0;

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

    {

        a[0].init();

        e=1;

        RD(n);

        char str[15];

        int i,j;

        FOR0(i,n) RD(j),RD(str),insert(str,j,i);

        build();

        find(s);

        printf("Case %d\n",++num);

        FOR0(i,n) PR(*mp[i]);

        puts("");

    }

}

 

  

 

你可能感兴趣的:(String)