现在的位置: 首页 > 综合 > 正文

HDU 2222 AC自动机

2019年02月27日 ⁄ 综合 ⁄ 共 2501字 ⁄ 字号 评论关闭

参考博客:点这里

总结:

1.建立trie树

2.构建fail指针

3.查找模式串

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
struct node
{
    node *next[26];
    node *fail;
    int cnt;
    node()
    {
        fail=NULL;
        cnt=0;
        memset(next,NULL,sizeof(next));
    }
}*q[555555];
char a[55],s[1111111];
int n;
void trie(char *c,node *root)
{
    node *p=root;
    int l=strlen(c);
    for(int i=0;i<l;i++)
    {
        int u=c[i]-'a';
        if(p->next[u]==NULL)
        {
            p->next[u]=new node();
        }
        p=p->next[u];
    }
    p->cnt++;
}
void buildac(node *root)
{
    int head=0,tail=0;
    root->fail=NULL;
    q[tail++]=root;
    while(head<tail)
    {
        node *u=q[head++];
        node *p=NULL;
        for(int i=0;i<26;i++)
        {
            if(u->next[i]!=NULL)
            {
                if(u==root)u->next[i]->fail=root;
                else
                {
                    p=u->fail;
                    while(p!=NULL)
                    {
                        if(p->next[i]!=NULL)
                        {
                            u->next[i]->fail=p->next[i];
                            break;
                        }
                        p=p->fail;
                    }
                    if(p==NULL)u->next[i]->fail=root;
                }
                q[tail++]=u->next[i];
            }
        }
    }
}
void query(node *root)
{
    int ans=0;
    int l=strlen(s);
    node *p=root;
    for(int i=0;i<l;i++)
    {
        int u=s[i]-'a';
        while(p->next[u]==NULL&&p!=root)p=p->fail;
        if(p->next[u]==NULL)p=root;
        else p=p->next[u];
        node *temp=p;
        while(temp!=root&&temp->cnt!=-1)
        {
            ans+=temp->cnt;
            temp->cnt=-1;
            temp=temp->fail;
        }
    }
    printf("%d\n",ans);
}
int main()
{
    int ca;
    scanf("%d",&ca);
    while(ca--)
    {
        node *root=new node();
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%s",a);
            trie(a,root);
        }
        scanf("%s",s);
        buildac(root);
        query(root);
    }
    return 0;
}

数组版

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<algorithm>
#include<string>
#include<cmath>
using namespace std;
struct node
{
    int fail;
    int next[26];
    int cnt;
}t[555555];
char a[55];
char s[1111111];
int q[555555];
int n;
int num;
void trie(char *c)
{
    int p=0;
    int l=strlen(c);
    for(int i=0;i<l;i++)
    {
        int u=c[i]-'a';
        if(t[p].next[u]==-1)
        {
            t[p].next[u]=++num;
            memset(t[num].next,-1,sizeof(t[num].next));
            t[num].cnt=0;
        }
        p=t[p].next[u];
    }
    t[p].cnt++;
}
void buildac()
{
    int fst=0,tail=0;
    t[0].fail=-1;
    q[tail++]=0;
    while(fst<tail)
    {
        int u=q[fst++];
        for(int i=0;i<26;i++)
        {
            if(t[u].next[i]!=-1)
            {
                if(u==0)t[t[u].next[i]].fail=0;
                else
                {
                    int p=t[u].fail;
                    while(p!=-1)
                    {
                        if(t[p].next[i]!=-1)
                        {
                            t[t[u].next[i]].fail=t[p].next[i];
                            break;
                        }
                        p=t[p].fail;
                    }
                    if(p==-1)t[t[u].next[i]].fail=0;
                }
                q[tail++]=t[u].next[i];
            }
        }
    }
}
int count()
{
    int p=0;
    int ans=0;
    int l=strlen(s);
    int u;
    for(int i=0;i<l;i++)
    {
        u=s[i]-'a';
        while(t[p].next[u]==-1&&p!=0)p=t[p].fail;
        p=t[p].next[u];
        if(p==-1)p=0;
        int temp=p;
        while(temp!=0&&t[temp].cnt!=-1)
        {
            if(t[temp].cnt)
            {
                ans+=t[temp].cnt;
                t[temp].cnt=-1;
            }
            temp=t[temp].fail;
        }
    }
    return ans;
}
void init()
{
    num=0;
    t[0].cnt=0;
    memset(t[0].next,-1,sizeof(t[0].next));
}
int main()
{
    int ca;
    scanf("%d",&ca);
    while(ca--)
    {
        init();
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%s",a);
            trie(a);
        }
        scanf("%s",s);
        buildac();
        printf("%d\n",count());
    }
    return 0;
}

【上篇】
【下篇】

抱歉!评论已关闭.