Cod sursa(job #1839023)

Utilizator tudi98Cozma Tudor tudi98 Data 2 ianuarie 2017 12:28:19
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.31 kb
#include <fstream>
#include <vector>
#include <iostream>
#include <queue>
using namespace std;

int n;
char text[1000000];
char s[10000];

struct Trie
{
    Trie *sons[26],*back;
    int count;
    vector<Trie*> G;
    Trie() {
        for (int i = 0; i < 26; i++)
            sons[i] = NULL;
        back = NULL;
        count = 0;
        G.clear();
    }
};

Trie *root = new Trie, *leafs[101];

Trie *addWord(Trie *T,char *c)
{
    if (*c == 0)
        return T;

    int nxt = *c - 'a';
    if (T->sons[nxt] == NULL)
        T->sons[nxt] = new Trie;

    return addWord(T->sons[nxt],c+1);
}

void bfs()
{
    queue<Trie*> Q;
    Q.push(root);
    while (!Q.empty())
    {
        Trie *T = Q.front(); Q.pop();
        for (int i = 0; i < 26; i++)        // pentru fiecare fiu caut muchia fail
        {
            if (T->sons[i] == NULL) continue;   // nu exista acest fiu

            Trie *u = T->back;       // pentru a calcula muchia fail pentru fiu ma folosesc de muchia fail a parintelui

            while (u != NULL && u->sons[i] == NULL)      // cat timp prefixul pentru parinte >= 1 si nu pot sa il fac prefix pentru fiu
                u = u->back;

            if (u == NULL)        // daca nu am gasit prefix muchia de intoarcere va fi catre radacina
                u = root;
            else
                u = u->sons[i];

            T->sons[i]->back = u;          // setam muchia fail pentru fiu
            u->G.push_back(T->sons[i]);

            Q.push(T->sons[i]);
        }
    }
}

void dfs(Trie *T)
{
    for (int i = 0; i < T->G.size(); i++)
    {
        dfs(T->G[i]);
        T->count += T->G[i]->count;
    }
}



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

    fin >> text;
    fin >> n;
    for (int i = 1; i <= n; i++)
    {
        fin >> s;
        leafs[i] = addWord(root,s);
    }

    bfs();

    Trie *T = root;
    for (char *c = text; *c; c++)
    {
        int nxt = *c - 'a';
        while (T != NULL && T->sons[nxt] == NULL)
            T = T->back;

        if (T == NULL)
            T = root;
        else
            T = T->sons[nxt];

        T->count++;
    }

    dfs(root);

    for (int i = 1; i <= n; i++)
        fout << leafs[i]->count << "\n";
}