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

AC自动机

时间:2020-01-23 19:54:59      阅读:87      评论:0      收藏:0      [点我收藏+]

标签:int   ifd   就是   cstring   open   com   for   stdout   res   

题源: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\n", tmp);
        if (tmp == 0) continue;
        for (int i = 1; i <= n; ++i)
        {
            if (ans[i] == tmp)
            printf("%s\n", p[i]);
        }
    }
}

AC自动机

标签:int   ifd   就是   cstring   open   com   for   stdout   res   

原文地址:https://www.cnblogs.com/jionkitten/p/12231090.html

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