Cod sursa(job #2356577)

Utilizator alexmisto342Turdean Alexandru alexmisto342 Data 26 februarie 2019 19:53:10
Problema Aho-Corasick Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.29 kb
#include <bits/stdc++.h>
#define ch(x) x-'a'
using namespace std;

struct Trie{
    int c;
    int word;
    Trie *father, *suffix, *solved;
    Trie *kid[26];

    Trie(Trie *nod, char ch) {
        word = 0;
        c = ch;
        father = nod;
        suffix = solved = NULL;
        for(int i = 0; i < 26; i++)
            kid[i] = NULL;
    }
};

void insert(Trie *&nod, string::iterator it, string::iterator end, int word)
{
    if(it == end)
    {
        nod->word = word;
        return;
    }

    if(nod->kid[ ch(*it) ] == NULL)
        nod->kid[ ch(*it) ] = new Trie(nod, ch(*it));

    insert(nod->kid[ ch(*it) ], it+1, end, word);
}

void aho(Trie *&root)
{
    queue<Trie*> q;

    for(int i = 0; i < 26; i++)
        if(root->kid[i])
            q.push(root->kid[i]);

    while(q.size())
    {
        Trie *nod = q.front();
        q.pop();

        if(nod->father == root)
            nod->suffix = root;
        else
        {
            Trie *suff = nod->father->suffix;
            int c = nod->c;

            while(suff != root && suff->kid[c] == NULL)
                suff = suff->suffix;

            if(suff->kid[c] != NULL)
                suff = suff->kid[c];

            nod->suffix = suff;

            if(suff->word)
                nod->solved = suff;
            else
                nod->solved = suff->solved;
        }
        for(int i = 0; i < 26; i++)
            if(nod->kid[i])
                q.push(nod->kid[i]);
    }
}

Trie *root;
string s,t;
int n;
int f[200];
int main()
{
    ifstream cin("ahocorasick.in");
    ofstream cout("ahocorasick.out");
    root = new Trie(NULL, 0);

    cin >> s;
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> t;
        insert(root, t.begin(), t.end(), i);
    }

    aho(root);
    Trie *state = root;
    for(auto i:s)
    {
        int c = ch(i);
        while(state != root && state->kid[c] == NULL)
            state = state->suffix;

        if(state->kid[c] != NULL)
            state = state->kid[c];

        Trie *ans = state;
        while(ans != NULL)
        {
            f[ans->word]++;
            ans = ans->solved;
        }
    }
    for(int i = 1; i <= n; i++)
        cout << f[i] << '\n';
    return 0;
}