Cod sursa(job #1969374)

Utilizator tudi98Cozma Tudor tudi98 Data 18 aprilie 2017 14:01:15
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.94 kb
#include <bits/stdc++.h>
using namespace std;

#define REP(i,a) for (int i = 0; i < a; i++)
#define FOR(i,a,b) for (int i = a; i <= b; i++)
#define ROF(i,a,b) for (int i = a; i >= b; i--)
#define FOREACH(it,x) for (auto it: (x))
#define pb push_back
#define SZ(x) ((int)(x).size())

int n;
char text[1000005];
char word[105][10005];

struct Trie {
    int cnt;
    Trie *sons[26],*bck;
    vector<Trie*> G;
    Trie() {
        cnt = 0; bck = 0;
        REP(i,26) sons[i] = 0;
        G = vector<Trie*>();
    }
};

Trie *leaf[105];
Trie *root = new Trie;

void addWord(Trie *T,char *c,int wordID)
{
    if (*c == 0) {
        leaf[wordID] = T;
        return;
    }
    int nxt = *c - 'a';
    if (T->sons[nxt] == 0)
        T->sons[nxt] = new Trie;
    addWord(T->sons[nxt],c+1,wordID);
}

void buildBackEdges()
{
    queue<Trie*> Q;
    Q.push(root);
    while (!Q.empty()) {
        Trie *parent = Q.front(); Q.pop();
        REP(i,26) if (parent->sons[i] != 0) {
            Trie *b = parent->bck;
            while (b != 0 && b->sons[i] == 0) b = b->bck;
            if (b == 0)
                b = root;
            else b = b->sons[i];
            parent->sons[i]->bck = b;
            b->G.pb(parent->sons[i]);
            Q.push(parent->sons[i]);
        }
    }
}

void dfs(Trie *T)
{
    FOREACH(it,T->G) {
        dfs(it);
        T->cnt += it->cnt;
    }
}

int main()
{
    ifstream fin("ahocorasick.in");
    ofstream fout("ahocorasick.out");

    fin >> text >> n;
    FOR(i,1,n) {
        fin >> word[i];
        addWord(root,word[i],i);
    }
    buildBackEdges();
    Trie *curr = root;
    for (char *c = text; *c; c++) {
        int nxt = *c - 'a';
        while (curr != 0 && curr->sons[nxt] == 0) curr = curr->bck;
        if (curr == 0) curr = root;
        else curr = curr->sons[nxt];
        curr->cnt++;
    }
    dfs(root);
    FOR(i,1,n) fout << leaf[i]->cnt << "\n";
}