Cod sursa(job #1553516)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 19 decembrie 2015 23:03:30
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.26 kb
#include <bits/stdc++.h>

using namespace std;

const int sigma = 'z' - 'a' + 1;
const int Nmax = 100 + 10;
const int Lenght = 1000000 + 10;

struct Trie
{
    int nr;

    Trie *prv;
    Trie *son[sigma];
    Trie *phi;

    Trie()
    {
        prv = NULL;
        for (int i = 0; i < sigma; ++i) son[i] = NULL;
        nr = 0;
    };
};

int n , i , last;

string s , sir;

Trie *term[Nmax] , *root;
pair < Trie* , char > q[Lenght];

Trie *add(Trie *node , int p)
{
    if (p == s.size()) return node;

    int ch = s[p] - 'a';
    if (node -> son[ch] == NULL)
        node -> son[ch] = new Trie,
        node -> son[ch] -> prv = node;
    return add(node -> son[ch] , p + 1);
}

void makePhi()
{
    Trie *crt , *node; char ch;

    root -> phi = root; root -> prv = root; int i;

    q[++last] = {root , 0};
    for (int j = 0; j < sigma; ++j)
        if (root -> son[j] != NULL)
        {
            root -> son[j] -> phi = root;
            q[++last] = {root -> son[j] , j};
        }
    for (i = 2; i <= last; i++)
    {
        tie(node , ch) = q[i];

        if (node -> prv != root)
        {
            crt = node -> prv -> phi;
            while (crt != root && crt -> son[ch] == NULL)
                crt = crt -> phi;
            if (crt -> son[ch] != NULL) crt = crt -> son[ch];
            node -> phi = crt;
        }

        for (int j = 0; j < sigma; ++j)
            if (node -> son[j] != NULL)
                q[++last] = {node -> son[j],j};
    }
}

void makeSol()
{
    Trie *node = root;
    for (int i = 0; i < sir.size(); ++i)
    {
        char ch = sir[i] - 'a';
        while (node != root && node -> son[ch] == NULL)
            node = node -> phi;
        if (node -> son[ch] != NULL) node = node -> son[ch];

        node -> nr++;
    }

    for (int i = last; i ; --i)
        q[i].first -> phi -> nr += q[i].first -> nr;
}

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

    fin >> sir;
    fin >> n; root = new Trie;
    for (i = 1; i <= n; ++i)
    {
        fin >> s;
        term[i] = add(root , 0);
    }

    makePhi();
    makeSol();

    for (i = 1; i <= n; ++i)
        fout << term[i] -> nr << '\n';

    return 0;
}