码迷,mamicode.com
首页 > 其他好文 > 详细

AC自动机

时间:2019-01-28 15:09:32      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:else   mat   strlen   text   ide   dong   模板   register   return   

时间有限,只过了板子和少数题目。。在应该搞DP的时候搞这个。。

关于AC自动机的介绍,LuoGu日报讲的挺好的,可以比较好的入门。

一、模板

技术分享图片
#include<bits/stdc++.h>
#define RG register
#define IL inline
#define LL long long
using namespace std;

IL int gi () {
    RG int x=0,w=0; char ch=0;
    while (ch<0||ch>9) {if (ch==-) w=1;ch=getchar();}
    while (ch>=0&&ch<=9) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return w?-x:x;
}

const int N=1e6+10;

int n,ans,tot[210];
char str[N],ss[210][110];

namespace AC_Automaton {
    queue <int> q;
    int num,cnt[N],f[N],tr[N][27];

    IL void New () {
        num=0;
        while (!q.empty()) q.pop();
        memset(f,0,sizeof(f));
        memset(tr,0,sizeof(tr));
        memset(cnt,0,sizeof(cnt));
    }
    
    IL void Insert (char s[],int id) {
        RG int i,p=0,now,len=strlen(s);
        for (i=0;i<len;++i) {
            now=s[i]-a+1;
            if (!tr[p][now]) tr[p][now]=++num;
            p=tr[p][now];
        }
        cnt[p]=id;
    }          
    
    IL void Get_Fail () {
        RG int i,p;
        for (i=1;i<=26;++i)
            if (tr[0][i]) q.push(tr[0][i]);
        while (!q.empty()) {
            p=q.front(),q.pop();
            for (i=1;i<=26;++i) 
                if (tr[p][i]) f[tr[p][i]]=tr[f[p]][i],q.push(tr[p][i]);
                else tr[p][i]=tr[f[p]][i];
                // *类似并查集路径压缩*
                // *所以可以一步到位*
        }
    }

    IL void Search (char s[]) {
        int i,j,p=0,len=strlen(s);
        for (i=0;i<len;++i) {
            p=tr[p][s[i]-a+1];
            for (j=p;j;j=f[j])
                if (cnt[j]) ++tot[cnt[j]];
        }
    }
}
using namespace AC_Automaton;

int main ()
{
    RG int i;
    while ((n=gi())!=0) {
        ans=0,New();
        memset(tot,0,sizeof(tot));
        for (i=1;i<=n;++i)
            scanf("%s",ss[i]),Insert(ss[i],i);
        scanf("%s",str); Get_Fail();
        Search(str);
        for (i=1;i<=n;++i)
            if (tot[i]>ans) ans=tot[i];
        printf("%d\n",ans);
        for (i=1;i<=n;++i)
            if (tot[i]==ans) printf("%s\n",ss[i]);
    }
    return 0;
}
BY BHLLX

我的不知道为什么跑的贼慢。。。

二、LuoguP2444病毒

硬是不会rand一个puts??对于一个刚入门AC自动机的人来说,这个题还是有点意思的。。

先建一颗AC自动机,每个串结尾打上标记。

我们这样考虑一下:

如果我们拿最后那个合法的序列去AC自动机上匹配,那么我们会发现它恰好能避开所有打了标记的节点,通过fail指针在AC自动机上打转。

那么我们是不是只要在这个AC自动机上找到一个不含任何病毒节点的环就好了??

怎么找??

 

AC自动机

标签:else   mat   strlen   text   ide   dong   模板   register   return   

原文地址:https://www.cnblogs.com/Bhllx/p/10329982.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!