Cod sursa(job #1947826)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 31 martie 2017 13:52:49
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.28 kb
#include <fstream>
#include <string>
#include <queue>
#include <vector>

using namespace std;

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

const int omega = 26;
const int nmax = 100;

int ans[nmax + 1];

struct Trie {
    vector< int > cine;
    Trie *pi, *fii[omega + 1];
    int cnt;

    Trie() {
        cnt = 0;
        for (int i = 0; i < omega; ++ i) {
            fii[ i ] = NULL;
        }
        pi = NULL;
    }
} *root;

vector< Trie* > ord;
queue< Trie* > q;

string cuv, s;

Trie* baga (Trie *nod, int pos, int ind) {
    if (pos == (int)s.size()) {
        nod -> cine.push_back( ind );
        return nod;
    }

    int x = s[ pos ] - 'a';
    if (nod -> fii[ x ] == NULL) {
        nod -> fii[ x ] = new Trie();
    }

    nod -> fii[ x ] = baga(nod -> fii[ x ], pos + 1, ind);
    return nod;
}

void bfs() {
    q.push(root);
    root -> pi = root;

    while (!q.empty()) {
        Trie *k = q.front(); q.pop();
        ord.push_back( k );

        for (int i = 0; i < omega; ++ i) {
            if (k -> fii[ i ] != NULL && k -> fii[ i ] -> pi == NULL) {
                q.push(k -> fii[ i ]);

                Trie *r = k -> pi;
                while (r != root && r -> fii[ i ] == NULL) {
                    r = r -> pi;
                }

                if (r -> fii[ i ] == NULL || k == root) {
                    k -> fii[ i ] -> pi = root;
                } else {
                    k -> fii[ i ] -> pi = r -> fii[ i ];
                }
            }
        }
    }
}

int main() {
    int n;
    fin >> cuv >> n;

    root = new Trie();

    for (int i = 0; i < n; ++ i) {
        fin >> s;
        root = baga(root, 0, i);
    }

    bfs();

    Trie *r = root;
    for (auto i : cuv) {
        int x = i - 'a';
        while (r != root && r -> fii[ x ] == NULL) {
            r = r -> pi;
        }

        if (r -> fii[ x ] == NULL) {
            r = root;
        } else {
            r = r -> fii[ x ];
        }
        ++ r -> cnt;
    }

    for (int i = ord.size() - 1; i >= 0; -- i) {
        for (auto j : ord[ i ] -> cine) {
            ans[ j ] = ord[ i ] -> cnt;
        }

        ord[ i ] -> pi -> cnt += ord[ i ] -> cnt;
    }

    for (int i = 0; i < n; ++ i) {
        fout << ans[ i ] << "\n";
    }

    fin.close();
    fout.close();
    return 0;
}