Cod sursa(job #2487438)

Utilizator Mihai145Oprea Mihai Adrian Mihai145 Data 4 noiembrie 2019 19:29:13
Problema Aho-Corasick Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.08 kb
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

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

const int SIGMA = 26;
const int NMAX = 100;
const int WORDMAX = 10000;
const int TEXTMAX = 1000000;

struct Trie
{
    Trie *sons[SIGMA];
    Trie *failLink, *outputLink;

    vector <int> wordList;
    int Count; ///dp

    Trie()
    {
        for(int i = 0; i < SIGMA; i++)
            sons[i] = NULL;

        failLink = outputLink = NULL;
        Count = 0;
    }
};

int N;
char text[TEXTMAX + 5], word[WORDMAX + 5];

queue < Trie* > Q;
vector < Trie* > antibfs;

int freq[NMAX + 5];

Trie *root = new Trie();

void Insert(Trie *node, char *s, int wordId)
{
    if(s[0] == '\0')
        node-> wordList.push_back(wordId);
    else
        {
            if(node-> sons[s[0] - 'a'] == NULL)
                node-> sons[s[0] - 'a'] = new Trie();

            Insert(node-> sons[s[0] - 'a'], s + 1, wordId);
        }
}

void ComputeLinks()
{
    root-> failLink = root-> outputLink = root;

    for(int i = 0; i < SIGMA; i++)
        if(root-> sons[i] != NULL)
            {
                root-> sons[i]-> failLink = root-> sons[i]-> outputLink = root;
                Q.push(root-> sons[i]);
            }

    while(!Q.empty())
    {
        Trie *node = Q.front(); Q.pop();

        for(int i = 0; i < SIGMA; i++)
            if(node-> sons[i] != NULL)
                {
                    Trie *failNode = node-> failLink;

                    while(failNode != root && failNode-> sons[i] != NULL)
                        failNode = failNode-> failLink;

                    if(failNode-> sons[i] != NULL && failNode-> sons[i] != node-> sons[i])
                        failNode = failNode-> sons[i];

                    node-> sons[i]-> failLink = failNode;

                    if((int)failNode-> wordList.size() != 0)
                        node-> sons[i]-> outputLink = failNode;
                    else
                        node-> sons[i]-> outputLink = failNode-> outputLink;

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

void Solve(char *t)
{
    Trie *node = root;

    while(t[0] != '\0')
    {
        while(node != root && node-> sons[t[0] - 'a'] == NULL)
            node = node-> failLink;

        if(node-> sons[t[0] - 'a'] != NULL)
            node = node-> sons[t[0] - 'a'];

        node-> Count++;
        t += 1;
    }

    Q.push(root);
    while(!Q.empty())
    {
        Trie *n = Q.front(); Q.pop();
        antibfs.push_back(n);

        for(int i = 0; i < SIGMA; i++)
            if(n-> sons[i] != NULL)
                Q.push(n-> sons[i]);
    }

    reverse(antibfs.begin(), antibfs.end());
    for(auto it : antibfs)
    {
        for(auto w : it-> wordList)
            freq[w] += it-> Count;

        it-> failLink-> Count += it-> Count;
    }

    for(int i = 1; i <= N; i++)
        fout << freq[i] << '\n';
}

int main()
{
    fin >> text;

    fin >> N;

    for(int i = 1; i <= N; i++)
    {
        fin >> word;
        Insert(root, word, i);
    }

    ComputeLinks();

    Solve(text);

    return 0;
}