Cod sursa(job #2286781)

Utilizator Mihai_PredaPreda Mihai Dragos Mihai_Preda Data 20 noiembrie 2018 19:06:02
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.98 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <queue>

using namespace std;

inline int toInt(char x)
{
    return x - 'a';
}

struct Trie
{
    Trie()
    {
        fail = nullptr;
        ap = 0;
        for(int i = 0; i < 26; ++i)
            child[i] = nullptr;
    }
    Trie* Insert(const char * s)
    {
        if(s[0] == '\0')
            return this;
        int c = toInt(s[0]);
        if(child[c] == nullptr)
            child[c] = new Trie();
        return child[c]->Insert(s+1);
    }
    void AddChildAps()
    {
        for(auto c:failChild)
        {
            c->AddChildAps();
            ap += c->ap;
        }
    }
    void ResetAp()
    {
        for(int i = 0; i < 26; ++i)
            if(child[i])
                child[i]->ResetAp();
        ap = 0;
    }
    Trie * child[26];
    Trie * fail;
    vector<Trie*> failChild;
    int ap;
};

class Aho
{
public:
    Aho(const vector<string> &v)
    {
        trie = new Trie;
        nodCuv.resize(v.size());
        for(int i = 0; i < v.size(); ++i)
            nodCuv[i] = trie->Insert(v[i].c_str());

        BFS();
    }
    vector<int> GetAp(const string &text)
    {
        Trie * current = trie;
        for(auto c:text)
        {
            while(current && !current->child[toInt(c)])
                current = current->fail;
            if(!current)
                current = trie;
            else
                current = current->child[toInt(c)];
            current->ap++;
        }
        trie->AddChildAps();
        vector<int> ret(nodCuv.size());
        for(int i = 0; i < ret.size(); ++i)
            ret[i] = nodCuv[i]->ap;
        trie->ResetAp();
        return ret;
    }
private:
    Trie * trie;
    vector<Trie*> nodCuv;

    void BFS()
    {
        queue<Trie*> q;
        q.push(trie);

        Trie * nod, * current;
        while(q.empty() == false)
        {
            nod = q.front();
            q.pop();

            for(int i = 0; i < 26; ++i)
                if(nod->child[i])
                {
                    current = nod->fail;
                    while(current && !current->child[i])
                        current = current->fail;
                    if(!current)
                        current = trie;
                    else
                        current = current->child[i];
                    nod->child[i]->fail = current;
                    current->failChild.push_back(nod->child[i]);
                    q.push(nod->child[i]);
                }
        }
    }
};

int main()
{
    ifstream in("ahocorasick.in");

    string s;
    in >> s;
    int n;
    in >> n;
    vector<string> v(n);
    for(int i = 0; i < n; ++i)
        in >> v[i];
    in.close();

    Aho aho(v);
    vector<int> rasp = aho.GetAp(s);

    ofstream out("ahocorasick.out");
    for(auto x:rasp)
        out << x << "\n";
    out.close();
    return 0;
}