HDU2222 Keywords Search + HDU2896病毒侵袭 AC自动机

虽然看明白了KMP和字典树,但是AC自动机还是没怎么理解QAQ...

附上讲解博客Orz:https://blog.csdn.net/qq_30346729/article/details/78835040

                               https://www.cnblogs.com/cjyyb/p/7196308.html

1.HDU2222 Keywords Search

kuangbin的模板,附上AC代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long

const int MAX=1000005;
int vis[MAX][26];
int fail[MAX];
int en[MAX];
int root,l;

int newnode()
{
    for(int i=0;i<26;i++)
        vis[l][i]=-1;
    en[l++]=0;
    return l-1;
}
void init()
{
    l=0;
    root=newnode();
}
void ins(char s[])
{
    int len=strlen(s);
    int now=root;
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'a';
        if(vis[now][id]==-1)
            vis[now][id]=newnode();
        now=vis[now][id];
    }
    en[now]++;
}
void build()
{
    queue<int>q;
    fail[root]=root;
    for(int i=0;i<26;i++)
    {
        if(vis[root][i]==-1)
            vis[root][i]=root;
        else
        {
            fail[vis[root][i]]=root;
            q.push(vis[root][i]);
        }
    }
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(int i=0;i<26;i++)
        {
            if(vis[now][i]==-1)
                vis[now][i]=vis[fail[now]][i];
            else
            {
                fail[vis[now][i]]=vis[fail[now]][i];
                q.push(vis[now][i]);
            }
        }
    }
}
int query(char s[])
{
    int len=strlen(s);
    int now=root;
    int ans=0;
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'a';
        now=vis[now][id];
        int tmp=now;
        while(tmp!=root)
        {
            ans+=en[tmp];
            en[tmp]=0;
            tmp=fail[tmp];
        }
    }
    return ans;
}

int main()
{
    char s[MAX];int n;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        init();//注意不能少!!
        for(int i=0;i<n;i++)
        {
            scanf("%s",s);
            ins(s);
        }
        build();
        scanf("%s",s);
        printf("%d\n",query(s));
    }
    return 0;
}

2.HDU2896病毒侵袭

这道题最大的坑点就在于没有规定全是小写字母。。。通过做这道题,对模板多了一点点点点理解,果然我还是太菜了啊55555...附上AC代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long

const int MAX=205*500;
int vis[MAX][128];//没有规定必须是小写字母,26不够,ASCII码值的范围:0-127
int fail[MAX];
int en[MAX];
int root,l;
int n;

int newnode()
{
    for(int i=0;i<128;i++)
        vis[l][i]=-1;
    en[l++]=0;
    return l-1;
}
void init()
{
    l=0;
    root=newnode();
}
void ins(char s[],int k)
{
    int len=strlen(s);
    int now=root;
    for(int i=0;i<len;i++)
    {
        int id=s[i];//没有规定必须是小写字母,所以直接用s[i]的ASCII码值
        if(vis[now][id]==-1)
            vis[now][id]=newnode();
        now=vis[now][id];
    }
    en[now]=k;//记录病毒的id
}
void build()
{
    queue<int>q;
    fail[root]=root;
    for(int i=0;i<128;i++)
    {
        if(vis[root][i]==-1)
            vis[root][i]=root;
        else
        {
            fail[vis[root][i]]=root;
            q.push(vis[root][i]);
        }
    }
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(int i=0;i<128;i++)
        {
            if(vis[now][i]==-1)
                vis[now][i]=vis[fail[now]][i];
            else
            {
                fail[vis[now][i]]=vis[fail[now]][i];
                q.push(vis[now][i]);
            }
        }
    }
}
bool used[505];
int query(char s[],int k)
{
    int len=strlen(s);
    int now=root;
    memset(used,false,sizeof(used));
    bool sign=false;
    for(int i=0;i<len;i++)
    {
        int id=s[i];
        now=vis[now][id];
        int tmp=now;
        while(tmp!=root)
        {
            if(en[tmp])
            {
                sign=true;
                used[en[tmp]]=true;
            }
            tmp=fail[tmp];
        }
    }
    if(!sign)
        return false;
    else
    {
        printf("web %d:",k);
        for(int i=1;i<=n;i++)
            if(used[i])
                printf(" %d",i);
        printf("\n");
        return true;//不要忘!
    }
}

int main()
{
    char s[10005];int m;
    while(scanf("%d",&n)==1)
    {
        init();//注意不能少!!
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s);
            ins(s,i);
        }
        build();
        scanf("%d",&m);
        int ans=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%s",s);
            if(query(s,i))
                ans++;
        }
        printf("total: %d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Cc_Sonia/article/details/82629600