Codechef 15.5 GRAPHCNT Dominator Tree
Codechef 14.5 ANUDTQ Splay+DFS序

Codechef 13.8 LYRC AC自动机

shinbokuow posted @ Nov 25, 2015 11:27:15 AM in Something with tags AC自动机 , 916 阅读

 

题目大意:
给定$W$个单词,每个单词长度不超过$|P|$,另有$N$句长度不超过$|S|$的歌词,问每个单词在所有歌词中一共出现的次数。
数据范围:单词和歌词包含大小写英文字母、数字和横杠,$W\leq{500},|P|\leq{1000},N\leq{100},|S|\leq{50000}$。
算法讨论:
直接利用AC自动机进行处理,对单词建出AC自动机,对于每句歌词在AC自动机上走,每走到一个节点都相当于要在这个节点在Fail树上到根节点的路径上都+1,我们可以通过在这个节点上打一个标记来实现,最后再DFS一遍Fail树就能得到答案了。
时空复杂度:
时间复杂度$O(W|P|+N|S|)$,空间复杂度$O(63W|P|)$。
代码:
#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define L 500010
int tr[L][63], cnt;
int change(char c) {
    if (c >= 'a' && c <= 'z')
        return c - 'a';
    if (c >= 'A' && c <= 'Z')
        return c - 'A' + 26;
    if (c >= '0' && c <= '9')
        return c - '0' + 52;
    return 62;
}
char s[50010];
vector<int> label[L];
queue<int> q;
int fail[L];
int head[L], nxt[L], to[L];
void addedge(int a, int b) {
    static int q = 1;
    to[q] = b;
    nxt[q] = head[a];
    head[a] = q++;
}
int c[L];
void dfs(int x) {
    for (int j = head[x]; j; j = nxt[j]) {
        dfs(to[j]);
        c[x] += c[to[j]];
    }
}
int ans[510];
int seq[L], fr, ta;
int main() {
#ifndef ONLINE_JUDGE
    freopen("tt.in", "r", stdin);
#endif
    int n, i, j, k, len, p, y;
    cin >> n;
    gets(s);
    for (i = 1; i <= n; ++i) {
        gets(s);
        len = strlen(s);
        p = 0;
        for (j = 0; j < len; ++j) {
            y = change(s[j]);
            if (!tr[p][y])
                tr[p][y] = ++cnt;
            p = tr[p][y];
        }
        label[p].push_back(i);
    }
    
    for (j = 0; j < 63; ++j)
        if (tr[0][j])
            q.push(tr[0][j]);
    int u, v, r;
    while (!q.empty()) {
        u = q.front();
        q.pop();
        for (j = 0; j < 63; ++j) {
            if ((v = tr[u][j])) {
                q.push(v);
                for (r = fail[u]; r && !tr[r][j]; r = fail[r]);
                fail[v] = tr[r][j];
            }
        }
    }
    
    for (i = 1; i <= cnt; ++i)
        addedge(fail[i], i);
    
    int q;
    cin >> q;
    gets(s);
    while (q--) {
        gets(s);
        len = strlen(s);
        p = 0;
        for (j = 0; j < len; ++j) {
            y = change(s[j]);
            while (p && !tr[p][y])
                p = fail[p];
            ++c[p = tr[p][y]];
        }
    }
    
    seq[ta++] = 0;
    while (fr != ta) {
        u = seq[fr++];
        for (j = head[u]; j; j = nxt[j])
            seq[ta++] = to[j];
    }
    for (i = ta - 1; i >= 0; --i)
        c[fail[seq[i]]] += c[seq[i]];
    
    
    for (i = 1; i <= cnt; ++i)
        for (j = 0; j < (int)label[i].size(); ++j)
            ans[label[i][j]] = c[i];
    
    for (i = 1; i <= n; ++i)
        printf("%d\n", ans[i]);
    
    return 0;
}

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter