字符串 AC自动机

AC自动机的板子简单版。

代码如下。

#include<bits/stdc++.h>
#define sc(x) scanf("%d",&x)
using namespace std;
const int maxn=1e6+10;
int n,cnt;
struct trie{
    int fail,num;
    int ch[30];
    #define fa(x) ac[x].fail
    #define nu(x) ac[x].num
}ac[maxn];
inline void insert(string s){
    int len=s.length();
    int now=0;
    for(int i=0;i<len;i++){
        if(!ac[now].ch[s[i]-'a'])
            ac[now].ch[s[i]-'a']=++cnt;
        now=ac[now].ch[s[i]-'a'];
    }
    nu(now)++;
}
//bfs
inline void getfail(){
    queue<int> q;
    for(int i=0;i<=26;i++)
        if(ac[0].ch[i])
            fa(ac[0].ch[i])=0,q.push(ac[0].ch[i]);
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(int i=0;i<26;i++){
            if(ac[now].ch[i]){
                fa(ac[now].ch[i])=ac[fa(now)].ch[i];
                q.push(ac[now].ch[i]);
            }
            else
                ac[now].ch[i]=ac[fa(now)].ch[i];
        }
    }
} 
inline int ask(string s){
    int len=s.length();
    int now=0,ans=0;
    for(int i=0;i<len;i++){
        now=ac[now].ch[s[i]-'a'];
        for(int j=now;j&&nu(j)!=-1;j=fa(j)){
            ans+=nu(j);
            nu(j)=-1;
        }
    }
    return ans;
}
int main()
{
    sc(n);
    string s;
    for(int i=1;i<=n;i++){
        cin>>s;
        insert(s);
    }
    fa(0)=0;
    getfail();
    cin>>s;
    printf("%d
",ask(s));
    return 0;
}

AC自动机节点存什么信息比较重要。

各个题目都不太一样。

需要个别的分析。

具体题目见题解。

加强版:

#include<bits/stdc++.h>
using namespace std;
int n,cnt;
const int maxn=1e6+10;
string c[200];
int en[maxn];
int ans[300];
struct acc{
    int fail,ch[26];
    #define fail(x) ac[x].fail
}ac[maxn];


inline void insert(string s,int x){
    int len=s.length();
    int p=0;
    for(int i=0;i<len;i++){
        if(!ac[p].ch[s[i]-'a']) ac[p].ch[s[i]-'a']=++cnt;
        p=ac[p].ch[s[i]-'a'];
    }
    en[p]=x;
}
inline void getfail(){
    queue<int> q;
    for(int i=0;i<26;i++)
        if(ac[0].ch[i]) 
            q.push(ac[0].ch[i]),fail(ac[0].ch[i])=0;
    while(q.size()){
        int p=q.front();
        q.pop();
        for(int i=0;i<26;i++){
            if(ac[p].ch[i]) 
                fail(ac[p].ch[i])=ac[fail(p)].ch[i],q.push(ac[p].ch[i]);
            else ac[p].ch[i]=ac[fail(p)].ch[i];
        }
    }
}
inline void work(string s){
    int len=s.length();
    int now=0;
    for(int i=0;i<len;i++){
        now=ac[now].ch[s[i]-'a'];
        for(int j=now;j;j=fail(j)) ans[en[j]]++;
    }
}

int main()
{
    while(scanf("%d",&n)&&n!=0){
        memset(en,0,sizeof(en));
        memset(ans,0,sizeof(ans));
        memset(ac,0,sizeof(ac));
        for(int i=1;i<=n;i++){
            cin>>c[i];
            insert(c[i],i);
        }
        getfail();
        string s;
        cin>>s;
        work(s);
        int now=0;
        for(int i=1;i<=n;i++)
            if(ans[i]>now) now=ans[i]; 
        printf("%d
",now);
        for(int i=1;i<=n;i++)
            if(ans[i]==now) cout<<c[i]<<endl;
    }
    // system("pause");
    return 0;
}
原文地址:https://www.cnblogs.com/ChrisKKK/p/11144051.html