Cod sursa(job #1229350)

Utilizator RazvanR104Razvan-Andrei Ciocoiu RazvanR104 Data 16 septembrie 2014 23:41:51
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.76 kb
#include <iostream>
#include <iomanip>
#include <fstream>

#include <algorithm>
#include <bitset>
#include <deque>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#if __cplusplus > 199711L
#include <unordered_map>
#include <unordered_set>
#endif

#include <cstdio>
#include <ctime>
#include <cmath>
#include <cstring>
#include <cstdlib>

using namespace std;

ifstream in("ahocorasick.in");
ofstream out("ahocorasick.out");

const int ALPHABET_SIZE = 26, LMAX = 1000010, LWORDMAX = 10010;

struct AhoCorasickAutomaton {
    int matches;
    vector<int> finish;

    AhoCorasickAutomaton *child[ALPHABET_SIZE], *fail;

    AhoCorasickAutomaton() {
        matches = 0;
        fail = 0;
        memset(child, 0, sizeof(child));
    }
} *AC;

vector<AhoCorasickAutomaton *> Q;

int N, start, finish;
int res[LWORDMAX];
char str[LMAX], word[LWORDMAX];

void insert_word(AhoCorasickAutomaton *node, char *str, int pos) {
    if (*str == 0) {
        node->finish.push_back(pos);
        return;
    }

    if (node->child[*str - 'a'] == 0) node->child[*str - 'a'] = new AhoCorasickAutomaton;
    insert_word(node->child[*str - 'a'], str + 1, pos);
}

void BF() {
    AhoCorasickAutomaton *fail;
    AC->fail = AC;

    Q.push_back(AC);
    while(start <= finish) {
        AhoCorasickAutomaton *node = Q[start++];

        for (int i = 0; i < ALPHABET_SIZE; ++i) {
            if (node->child[i] == 0) continue;

            for (fail = node->fail; fail != AC && fail->child[i] == 0; fail = fail->fail);
            if (fail->child[i] != 0 && fail->child[i] != node->child[i]) fail = fail->child[i];

            node->child[i]->fail = fail;
            Q.push_back(node->child[i]);
            ++finish;
        }
    }

    AC->fail = 0;
}

void ABF() {
    while(finish >= 0) {
        AhoCorasickAutomaton *node = Q[finish--];
        if (node->fail != 0) node->fail->matches += node->matches;

        for (int i = 0; i < (int)node->finish.size(); ++i)
            res[node->finish[i]] = node->matches;
    }
}

int main() {
    int i;

    in.getline(str, LMAX);
    in >> N;
    in.getline(word, LWORDMAX);

    AC = new AhoCorasickAutomaton;

    for (i = 1; i <= N; ++i) {
        in.getline(word, LWORDMAX);
        insert_word(AC, word, i);
    }


    BF();
    AhoCorasickAutomaton *_AC = AC;
    for (i = 0; str[i]; ++i) {
        for ( ; _AC != AC && _AC->child[str[i] - 'a'] == 0; _AC = _AC->fail);
        if (_AC->child[str[i] - 'a'] != 0) _AC = _AC->child[str[i] - 'a'];
        ++_AC->matches;
    }
    ABF();

    for (i = 1; i <= N; ++i) out << res[i] << '\n';

    in.close(), out.close();
    return 0;
}