AC自动机

Posted jionkitten

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC自动机相关的知识,希望对你有一定的参考价值。

题源:https://www.luogu.com.cn/problem/P3796

debug了一下午发现代码又抄错了,数组大小也开错了,数据范围搞混了。。

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <queue>
//#define LOCAL
//#define fre
#define maxn 1000005
using namespace std;
char s[maxn], p[155][75];
int n;
int nex[10510][26], fail[10510], e[10510], last[10510], ans[155]; //一开始这里开成了75.。。
struct Tire
{
    int cnt;
    void init()
    {
        cnt = 1;
        memset(nex, 0xff, sizeof(nex));
        memset(e, 0, sizeof(e));
        memset(last, 0, sizeof(last));
    }
    void insert(char s[], int t)
    {
        int len = strlen(s);
        int now = 0;
        for (int i = 0; i < len; ++i)
        {
            if (nex[now][s[i] - a] == -1)
                nex[now][s[i] - a] = cnt++;
            now = nex[now][s[i] - a];
        }
        e[now] = t;
    }
    void build()
    {
        queue<int> q;
        fail[0] = 0; last[0] = 0;
        for (int i = 0; i < 26; ++i)
        {
            if (nex[0][i] == -1) nex[0][i] = 0;
            else
            {
                fail[nex[0][i]] = 0;
                q.push(nex[0][i]);
            }
        }
        while (!q.empty())
        {
            int now = q.front(); q.pop();
            for (int i = 0; i < 26; ++i)
            {
                if (nex[now][i] == -1)
                {
                    nex[now][i] = nex[fail[now]][i];
                }
                else
                {
                    fail[nex[now][i]] = nex[fail[now]][i];
                    last[nex[now][i]] = e[fail[nex[now][i]]] ? fail[nex[now][i]] : last[fail[nex[now][i]]];//last优化,就是这里抄错了555
                    q.push(nex[now][i]);
                }
            }
        }
    }
    int query(char p[], int n)
    {
        int len = strlen(p);
        int now = 0, res = 0;
        for (int i = 0; i < len; ++i)
        {
            now = nex[now][p[i] - a];
            for (int j = now; j; j = last[j])
            {
                ans[e[j]]++;
                #ifdef LOCAL
                if (i == 2) cout << j << " " << e[j] << endl;
                if (e[j] == 5) cout << i << endl;
                #endif
            }
        }
        for (int i = 1; i <= n; ++i)
        {
            #ifdef LOCAL
            cout << i << " : " << ans[i] << endl;
            #endif
            res = max(res, ans[i]);
        }
        return res;
    }
};

int main()
{
    #ifdef fre
    freopen("in.in", "r", stdin);
    freopen("out.txt", "w", stdout);
    #endif
    Tire tr;
    while (scanf("%d", &n) && n)
    {
        tr.init();
        memset(ans, 0, sizeof(ans));
        for (int i = 1; i <= n; ++i) //注意从1开始,0已经被不断跳转回根节点占用了
        {
            scanf("%s", p[i]);
            tr.insert(p[i], i);
        }
        tr.build();
        scanf("%s", s);
        int tmp = tr.query(s, n);
        printf("%d
", tmp);
        if (tmp == 0) continue;
        for (int i = 1; i <= n; ++i)
        {
            if (ans[i] == tmp)
            printf("%s
", p[i]);
        }
    }
}

以上是关于AC自动机的主要内容,如果未能解决你的问题,请参考以下文章

POJ3691DNA repair(AC自动机,DP)

HDU4057 Rescue the Rabbit(AC自动机+状压DP)

Codeforces 86C Genetic engineering(AC自动机+DP)

POJ1699 Best Sequence(AC自动机+状压DP)

POJ - 2778 ~ HDU - 2243 AC自动机+矩阵快速幂

HDU2457 DNA repair(AC自动机+DP)