AC自动机 LA 4670 Dominating Patterns

 

题目传送门

题意:训练指南P216

分析:求出现最多次数的字串,那么对每个字串映射id,cnt记录次数求最大就可以了。

#include <bits/stdc++.h>
using namespace std;

const int N = 150 + 5;
const int NODE = N * 70;
const int LEN = 1e6 + 5;
const int SIZE = 26;
struct AC   {
    int ch[NODE][SIZE], fail[NODE], val[NODE], cnt[N], sz;
    map<string, int> ms;
    void clear(void)    {
        memset (ch[0], 0, sizeof (ch[0]));
        memset (cnt, 0, sizeof (cnt));
        sz = 1; val[0] = 0;
        ms.clear ();
    }
    int idx(char c) {
        return c - 'a';
    }
    void insert(char *P, int id)    {
        ms[string (P)] = id;
        int u = 0;
        for (int c, i=0; P[i]; ++i)    {
            c = idx (P[i]);
            if (!ch[u][c])  {
                memset (ch[sz], 0, sizeof (ch[sz]));
                val[sz] = 0;    ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = id;
    }
    void build(void)    {
        queue<int> que; fail[0] = -1;
        int u;
        for (int i=0; i<SIZE; ++i)  {
            u = ch[0][i];
            if (u)  {
                fail[u] = 0;    que.push (u);
            }
        }
        while (!que.empty ())   {
            u = que.front ();   que.pop ();
            for (int i=0; i<SIZE; ++i)  {
                int &v = ch[u][i];
                if (!v) {
                    v = ch[fail[u]][i]; continue;
                }
                que.push (v);
                fail[v] = ch[fail[u]][i];
            }
        }
    }
    void query(char *T)  {
        int u = 0, v;
        for (int c, i=0; T[i]; ++i)    {
            c = idx (T[i]);
            u = ch[u][c];   v = u;
            cnt[val[v]]++;
        }
    }
}ac;
char pattern[N][75], text[LEN];
int n;

void solve(void)    {
    int best = -1;
    for (int i=1; i<=n; ++i)    {
        if (ac.cnt[i] > best)   best = ac.cnt[i];
    }
    printf ("%d\n", best);
    for (int i=1; i<=n; ++i)    {
        if (ac.cnt[ac.ms[string (pattern[i])]] == best)   {
           printf ("%s\n", pattern[i]);
        }
    }
}

int main(void)    {
    while (scanf ("%d", &n) == 1) {
        if (!n) break;
        ac.clear ();
        for (int i=1; i<=n; ++i) {
            scanf ("%s", &pattern[i]);
            ac.insert (pattern[i], i);
        }
        ac.build ();
        scanf ("%s", &text);
        ac.query (text);
        solve ();
    }

    return 0;
}

  

posted @ 2016-01-12 11:07  Running_Time  阅读(163)  评论(0编辑  收藏  举报