Cod sursa(job #2448042)

Utilizator alextodoranTodoran Alexandru Raul alextodoran Data 15 august 2019 15:30:03
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.32 kb

#include <bits/stdc++.h>

using namespace std;

const int L_MAX = 1000002;
const int N_MAX = 102;
const int W_MAX = 10002;
const int MEM_MAX = 15002;

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

struct Trie
{
    int index;
    Trie* sons[26];
    Trie* maxPref;
    int apSubstr;
};

Trie mem[MEM_MAX];
int mempos = 0;

Trie* newTrie ()
{
    return &mem[mempos++];
}

Trie* Root = newTrie();

Trie* pos[N_MAX];

Trie* trieInsert(Trie* root, char* str)
{
    if(str[0] == '\0')
        return root;
    else
    {
        if(root->sons[str[0] - 'a'] == NULL)
            root->sons[str[0] - 'a'] = newTrie();
        return trieInsert(root->sons[str[0] - 'a'], str + 1);
    }
}

char a[L_MAX];
int n;
string w[N_MAX];

queue <Trie*> q;

vector <Trie*> order;

void bfs ()
{
    Root->maxPref = Root;
    q.push(Root);
    while(!q.empty())
    {
        Trie* root = q.front();
        order.push_back(root);
        q.pop();
        for(int i = 0; i < 26; i++)
            if(root->sons[i] != NULL)
            {
                root->sons[i]->maxPref = root->maxPref;
                while(root->sons[i]->maxPref != Root && root->sons[i]->maxPref->sons[i] == NULL)
                    root->sons[i]->maxPref = root->sons[i]->maxPref->maxPref;
                if(root->sons[i]->maxPref->sons[i] != NULL && root != Root)
                    root->sons[i]->maxPref = root->sons[i]->maxPref->sons[i];
                q.push(root->sons[i]);
            }
    }
}

void getFreq ()
{
    Trie* p = Root;
    int lga = strlen(a);
    for(int i = 0; i < lga; i++)
    {
        while(p != Root && p->sons[a[i] - 'a'] == NULL)
            p = p->maxPref;
        if(p->sons[a[i] - 'a'] != NULL)
            p = p->sons[a[i] - 'a'];
        p->apSubstr++;
    }
}

void getAnswer ()
{
    reverse(order.begin(), order.end());
    for(Trie* node : order)
        node->maxPref->apSubstr += node->apSubstr;
}

char str[W_MAX];

int main()
{
    fin >> a;
    fin >> n;
    for(int i = 1; i <= n; i++)
    {
        fin >> w[i];
        strcpy(str, w[i].c_str());
        pos[i] = trieInsert(Root, str);
    }
    bfs();
    getFreq();
    getAnswer();
    for(int i = 1; i <= n; i++)
        fout << pos[i]->apSubstr << "\n";
    return 0;
}