AC 自动机

  AC 自动机可以用来处理多模式匹配,AC 自动机是以 TRIE 的结构为基础 ,结合 KMP 的思想 建立的。

  ** 具体步骤 **

  1.构建 Trie

  2.构建失配指针

  3.进行多模式匹配

  例题  洛谷3808  AC自动机(简单版)

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int read()
{
    int k=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) k=k*10+c-'0';return k*f;
}
const int N=1000055;
int n,m,fail[N];
int tot,ch[N][26],val[N];
char s[N];
queue<int> q;
void ins(char *s) //构建trie 
{
    int now=0;
    for(int i=0;s[i];i++)
        if(!ch[now][s[i]-'a'])
            ch[now][s[i]-'a']=++tot,now=ch[now][s[i]-'a'];
        else now=ch[now][s[i]-'a'];
    val[now]++;
}
void build() //构建fail数组和字典图 
{
    for(int i=0;i<26;i++)
        if(ch[0][i])
            q.push(ch[0][i]);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=0;i<26;i++)
            if(ch[u][i])
                fail[ch[u][i]]=ch[fail[u]][i],q.push(ch[u][i]);
            else ch[u][i]=ch[fail[u]][i];
    }
}
int query(char *s) //多模式匹配 
{
    int now=0,ans=0;
    for(int i=0;s[i];i++)
    {
        now=ch[now][s[i]-'a'];
        for(int j=now;j&&val[j]!=-1;j=fail[j])
            ans+=val[j],val[j]=-1;
    }
    return ans;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        scanf("%s",s),ins(s);
    build(); 
    scanf("%s",s);
    printf("%d\n",query(s));
    return 0;
}

 

 

  洛谷P3796 AC自动机加强版

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int read()
{
    int k=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) k=k*10+c-'0';return k*f;
}
const int N=1000055;
int n,m,fail[N],sum[N];
int tot,ch[N][26],val[N];
char t[155][75];
char s[N];
queue<int> q;
void ins(int i,char *s) 
{
    int now=0;
    for(int i=0;s[i];i++)
        if(!ch[now][s[i]-'a'])
            ch[now][s[i]-'a']=++tot,now=ch[now][s[i]-'a'];
        else now=ch[now][s[i]-'a'];
    val[now]=i;
}
void build() 
{
    for(int i=0;i<26;i++)
        if(ch[0][i])
            q.push(ch[0][i]);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=0;i<26;i++)
            if(ch[u][i])
                fail[ch[u][i]]=ch[fail[u]][i],q.push(ch[u][i]);
            else ch[u][i]=ch[fail[u]][i];
    }
}
int query(char *s) //多模式匹配 
{
    int maxn=0,now=0;
    for(int i=0;s[i];i++)
    {
        now=ch[now][s[i]-'a'];
        for(int j=now;j;j=fail[j])
            if(val[j])
            {
                sum[val[j]]++;
                if(sum[val[j]]>maxn) maxn=sum[val[j]];
            }
    }    
    return maxn;
}
int main()
{
    while(n=read())
    {
        for(int i=1;i<=n;i++)
            scanf("%s",t[i]),ins(i,t[i]);
        build();
        scanf("%s",s);
        int maxn=query(s);
        int ans=0;
        printf("%d\n",maxn);
        for(int i=1;i<=n;i++)
            if(sum[i]==maxn) 
                printf("%s\n",t[i]);
        for(int i=0;i<=tot;i++)
            val[i]=fail[i]=0,memset(ch[i],0,sizeof(ch[i]));
        for(int i=1;i<=n;i++) sum[i]=0;
        tot=0;
    }
    return 0;
}
posted @ 2020-01-09 20:28  waing  阅读(137)  评论(0)    收藏  举报