Cod sursa(job #2717255)

Utilizator Mihai145Oprea Mihai Adrian Mihai145 Data 6 martie 2021 20:54:01
Problema Aho-Corasick Scor 100
Compilator cpp-32 Status done
Runda Arhiva educationala Marime 3.04 kb
#include <fstream>
#include <string>
#include <queue>
#include <vector>
#include <algorithm>

using namespace std;

ifstream cin("ahocorasick.in");
ofstream cout("ahocorasick.out");

const int SIGMA = 26;

struct Node {
    Node* children[SIGMA];
    Node* failLink;
    vector <int> wordList;
    int cnt;

    Node() {
        for(int i = 0; i < SIGMA; i++) {
            children[i] = NULL;
        }

        failLink = NULL;
        cnt = 0;
    }
};

Node *aho = new Node;

string text, s;
int N, freq[100 + 2];

void Insert(Node *node, int index, int wordId) {
    if(index == (int)s.size()) {
        node->wordList.push_back(wordId);
        return;
    } else {
        if(node-> children[s[index] - 'a'] == NULL)
            node-> children[s[index] - 'a'] = new Node;
        Insert(node-> children[s[index] - 'a'], index + 1, wordId);
    }
}

void ComputeAhoLinks() {
    aho-> failLink = aho;

    queue <Node*> Q;
    for(int i = 0; i < SIGMA; i++) {
        if(aho-> children[i] != NULL) {
            aho-> children[i]-> failLink = aho;
            Q.push(aho-> children[i]);
        }
    }

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

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

                while(failNode != aho && failNode-> children[i] == NULL) {
                    failNode = failNode-> failLink;
                }

                if(failNode-> children[i] != NULL && failNode-> children[i] != node-> children[i]) {
                    failNode = failNode-> children[i];
                }

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

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

void Solve() {
    Node *node = aho;

    for(int i = 0; i < (int)text.size(); i++) {
        while(node != aho && node-> children[text[i] - 'a'] == NULL) {
            node = node-> failLink;
        }

        if(node-> children[text[i] - 'a'] != NULL) {
            node = node-> children[text[i] - 'a'];
        }

        node-> cnt++;
    }

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

    Q.push(aho);

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

        antibfs.push_back(node);

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

    reverse(antibfs.begin(), antibfs.end());

    for(Node* node : antibfs) {
        for(int wordId : node-> wordList) {
            freq[wordId] += node-> cnt;
        }

        node->failLink->cnt += node->cnt;
    }

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

int main() {
    cin >> text;

    cin >> N;
    for(int i = 1; i <= N; i++) {
        cin >> s;
        Insert(aho, 0, i);
    }

    ComputeAhoLinks();

    Solve();

    return 0;
}