AC自动机

来源:互联网 发布:淘宝苹果充电器 编辑:程序博客网 时间:2024/04/30 17:11

关于AC自动机,http://www.cnblogs.com/kuangbin/p/3164106.html这个博客讲的非常清楚。

AC自动机基本就是trie和kmp的结合,实现起来也没有特别麻烦的细节,比kmp甚至还好写。关于next数组和fail数组,fail数组就是kmp中的next数组,只不过fail数组是针对很多组字符串而kmp中的next只有一个字符串。AC自动机中的fail数组在查询过程中完全没有用到,查询用到的是一个next数组,next[now][buf[i]]就是指在当前匹配是now的情况下,下一个字符是buf[i]的最佳匹配。

HDU 2222

#include <iostream>#include <queue>#include <cstring>#include <string>#include <cstdio>using namespace std;int n;const int N = 10010;class AC_auto{    public:        int next[N*52][26],fail[N*52],end[N*52];        int root,L;        int newnode()        {            for (int i = 0; i < 26; i++)            {                next[L][i] = -1;            }            end[L++] = 0;            return L-1;        }        void init()        {            L = 0;            root = newnode();        }               void insert(char buf[])       {            int now = root;            int len = strlen(buf);            for (int i = 0 ; i < len; i++)            {                int w = buf[i]-'a';                if (next[now][w] == -1)                {                    next[now][w] = newnode();                }                now = next[now][w];            }            end[now] += 1;       }                 void build()        {            queue<int> Q;            fail[root] = root;            for (int i =0; i < 26; i++)            {                if (next[root][i] == -1)                    next[root][i] = root;                else                 {                    fail[next[root][i]] = root;                    Q.push(next[root][i]);                }            }            while (!Q.empty())            {                int now = Q.front();                Q.pop();                for(int i = 0; i < 26; i++)                {                    if (next[now][i] == -1)                    {                        next[now][i] = next[fail[now]][i];                    }                    else                    {                        fail[next[now][i]] = next[fail[now]][i];                        Q.push(next[now][i]);                    }                }            }        }        int query(char buf[])        {            int ans = 0;            int now = root;            int len = strlen(buf);            for(int i = 0; i < len; i++)            {                int w = buf[i] - 'a';                now = next[now][w];                int temp = now;                while (temp != root)                {                    ans += end[temp];                    end[temp] = 0;                    temp = fail[temp];                }            }            return ans;        }};AC_auto a;void solve(){    int m;    scanf("%d",&m);    a.init();    char buf[100];    char target[1001000];    for (int i = 0; i < m; i++)    {       scanf("%s",buf);      a.insert(buf);     }    a.build();    scanf("%s",target);    printf("%d\n",a.query(target));}int main(){    scanf("%d",&n);    for (int i = 0; i < n; i++)    {        solve();    }    return 0;}

HDU 2896

#include <iostream>#include <queue>#include <cstring>#include <vector>#include <algorithm>#include <cstdio>using namespace std;const int N = 100000;class AC_auto{    public:        int next[N*10][128],end[N*52],fail[N*52];        int root,L;        int newnode()        {            for (int i = 0; i < 128; i++)            {                next[L][i] = -1;            }            end[L++] = 0;            return L -1;        }        void init()        {            L = 0;            root = newnode();        }            void insert(char buf[],int k)        {            int len = strlen(buf);            int now = root;            for (int i = 0 ; i < len; i++)            {                int w = buf[i];                if (next[now][w] == -1)                {                    next[now][w] = newnode();                }                now = next[now][w];            }            end[now] = k;         }        void build()        {            queue<int> Q;            fail[root] = root;            for (int i = 0; i < 128; i++)            {                if (next[root][i] == -1)                    next[root][i] = root;                else                {                    fail[next[root][i]] = root;                    Q.push(next[root][i]);                }            }            while (!Q.empty())            {                int now = Q.front();                Q.pop();                for(int i = 0; i < 128; i++)                {                    if (next[now][i] == -1)                    {                        next[now][i] = next[fail[now]][i];                    }else                    {                        fail[next[now][i]] = next[fail[now]][i];                        Q.push(next[now][i]);                    }                }                        }        }        vector<int> *query(char buf[],vector<int>* a)        {            a->clear();            int now = root;            int len = strlen(buf);            for (int i = 0; i < len; i++)            {                int w = buf[i];                now = next[now][w];                int temp = now;                while(temp != root)                {                    if (end[temp] != 0)                    {                        a->push_back(end[temp]);                    }                    temp = fail[temp];                }            }            return a;        }};AC_auto ac;int n;int m;void init(){    scanf("%d",&n);    ac.init();    char buf[300];    for (int i = 0; i < n; i++)    {        scanf("%s",buf);        ac.insert(buf,i+1);    }    ac.build();}void solve(){    scanf("%d",&m);    char buf[11000];    vector<int> a;    int sum = 0;    for (int i = 1; i <= m ;i++)    {        scanf("%s",buf);        ac.query(buf,&a);         sort(a.begin(),a.end());        if (a.size() == 0)            continue;        printf("web %d:",i);        sum++;        for (int j = 0; j < a.size(); j++)        {            if (j == 0 || a[j] != a[j-1])            {                printf(" %d",a[j]);            }        }        printf("\n");    }    printf("total: %d\n",sum);}int main(){    init();    solve();    return 0;}

HDU 3065

#include <iostream>#include <memory.h>#include <queue>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 60000;class AC_auto{    public:        int next[N][26],end[N],d[N],fail[N];        int root,L;        int newnode()        {            for(int i = 0; i< 26; i++)                next[L][i] = -1;            end[L] = 0;            L++;            return L-1;        }        void init()        {            L = 0;            root = newnode();            memset(d,0,sizeof(d));        }                    void insert(char buf[],int k)        {            int now = root;            int len = strlen(buf);            for(int i = 0; i < len; i++)            {                int w = buf[i]-'A';                if (next[now][w] == -1)                {                    next[now][w] = newnode();                }                now = next[now][w];            }            end[now] = k;        }        void build()        {            queue<int> Q;            fail[root] = root;            for(int i = 0; i < 26;i++)            {                if (next[root][i] == -1)                    next[root][i] = root;                else                {                    fail[next[root][i]] = root;                    Q.push(next[root][i]);                }            }            while (!Q.empty())            {                int now = Q.front();                Q.pop();                for (int i = 0; i < 26; i++)                {                    if (next[now][i] == -1)                    {                        next[now][i] = next[fail[now]][i];                    }                    else                    {                        fail[next[now][i]] = next[fail[now]][i];                         Q.push(next[now][i]);                    }                }            }        }        void query(char buf[])        {            int len = strlen(buf);            int now = root;            for(int i = 0; i < len; i++)            {                if (buf[i] >= 'A' && buf[i] <= 'Z')                {                    int w = buf[i] - 'A';                    now = next[now][w];                }else                     now = root;                int temp = now;                while (temp != root)                {                    if (end[temp])                    {                        d[end[temp]]++;                    }                                       temp = fail[temp];                }            }        }};vector<string> s;int n;AC_auto ac;char buf[2100000];void init(){    char buf[100];    ac.init();    s.clear();    for (int i = 0; i < n; i++)    {        scanf("%s",buf);        ac.insert(buf,i+1);        s.push_back(string(buf));    }    ac.build();}void solve(){    scanf("%s",buf);    ac.query(buf);    for (int i = 0; i < n; i++)    {        if (ac.d[i+1])        {            printf("%s: %d\n",s[i].c_str(),ac.d[i+1]);        }    } }int main(){    while (scanf("%d",&n) != EOF){    init();    solve();    }    return 0;}


0 0