Cod sursa(job #2487449)

Utilizator Mihai145Oprea Mihai Adrian Mihai145 Data 4 noiembrie 2019 19:40:40
Problema Aho-Corasick Scor 10
Compilator cpp-32 Status done
Runda Arhiva educationala Marime 3.1 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)node-> sons[i]-> failLink-> wordList.size() != 0)
                    node-> sons[i]-> outputLink = node-> sons[i]-> failLink;
                else
                    node-> sons[i]-> outputLink = node-> sons[i]-> failLink-> 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++;
    }

    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 n : antibfs)
    {
        for(auto wordId : n-> wordList)
            freq[wordId] += n-> Count;

        if(n-> failLink != NULL) {
            n-> failLink-> Count += n-> 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;
}