SCOI2012 喵星球上的点名

题意就不说了, 反正是中文;
正解应该是后缀数组, 但是AC自动机可以强行过, 只是比较慢;
对于询问串建AC自动机, 然后暴力把每个喵星人暴力在树上跑, 然后。。。就没有然后了。

#include <bits/stdc++.h>

const int mx_n = 2e4 + 10;
const int mx_m = 5e4 + 10;
const int mx_node = 1e5 + 10;
#define pb push_back
#define rep(i, s, t) for(register int i = s; i <= t; ++i)

using namespace std;

template <class T>
T read(T x = 0) {
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9')
        x = x*10 + c-'0', c = getchar();
    return x;
}

vector<int> G[mx_n];
int n, m, Ans[mx_m], Cat[mx_n];

namespace aho_corasick {
    queue<int> Q;
    int tot, fail[mx_node];
    vector<int> val[mx_node];
    map<int, int> ch[mx_node];

    void Bfs_fail() {
        Q.push(0);
        while(!Q.empty()) {
            int u = Q.front(); Q.pop();
            for(map<int, int>::iterator it = ch[u].begin(); it != ch[u].end(); ++it) {
                int x = it -> first, y = it -> second;
                if(u) {
                    int t = fail[u];
                    for(; t && !ch[t][x]; t = fail[t]);
                    fail[y] = ch[t][x];
                }Q.push(y);
            }
        }
    }
}using namespace aho_corasick;

int s[mx_n], vis[mx_m];
void Query(int x) {
    int u = 0, top = 0;
    rep(i, 0, (int) G[x].size()-1) {
        int id = G[x][i];
        for(; u && !ch[u][id]; u = fail[u]);
        for(int v = (u=ch[u][id]); v; v = fail[v])
            rep(j, 0, (int)val[v].size()-1) if(!vis[val[v][j]]) {
                ++Cat[x], ++Ans[val[v][j]], vis[s[++top]=val[v][j]] = 1;
            }
    }rep(i, 1, top) vis[s[i]] = 0;
}

void input() {
    n = read<int>(), m = read<int>();
    rep(i, 1, n) rep(Case, 0, 1) {
        int len = read<int>();
        while(len--) G[i].pb(read<int>());
        G[i].pb(10002);
    }rep(i, 1, m) {
        int u = 0;
        int len = read<int>();
        while(len--) {
            int x = read<int>();
            if(!ch[u][x]) ch[u][x] = ++tot;
            u = ch[u][x];
        }val[u].pb(i);
    }Bfs_fail();
}

int main() {
    input();
    rep(i, 1, n) Query(i);
    rep(i, 1, m) printf("%d
", Ans[i]);
    rep(i, 1, n) 
        printf("%d%c", Cat[i], i ^ n? ' ': '
');
    return 0;
}
原文地址:https://www.cnblogs.com/pbvrvnq/p/8530142.html