Cod sursa(job #2810315)

Utilizator buzu.tudor67Tudor Buzu buzu.tudor67 Data 29 noiembrie 2021 00:07:08
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.76 kb
#include <bits/stdc++.h>
using namespace std;

class Trie{
private:
    static const int ALPHABET_SIZE = 26;
    static const int FIRST_ELEM = 'a';
    int matchCount;
    Trie* suffixLink;
    vector<Trie*> reverseSuffixLinks;
    Trie* children[ALPHABET_SIZE];

    void updateMatchCounts(Trie* node){
        for(Trie* nextNode: node->reverseSuffixLinks){
            updateMatchCounts(nextNode);
            node->matchCount += nextNode->matchCount;
        }
    }

public:
    Trie(){
        matchCount = 0;
        suffixLink = NULL;
        reverseSuffixLinks.clear();
        fill(children, children + ALPHABET_SIZE, (Trie*)NULL);
    }

    void insert(const string& WORD){
        Trie* node = this;
        for(char c: WORD){
            int edgeID = c - FIRST_ELEM;
            if(node->children[edgeID] == NULL){
                node->children[edgeID] = new Trie();
            }
            node = node->children[edgeID];
        }
    }

    void insertAllWords(const vector<string>& WORDS){
        for(const string& WORD: WORDS){
            insert(WORD);
        }
    }

    void createSuffixLinks(){
        Trie* root = this;

        queue<Trie*> q;
        for(int edgeID = 0; edgeID < ALPHABET_SIZE; ++edgeID){
            if(root->children[edgeID] != NULL){
                root->children[edgeID]->suffixLink = root;
                root->reverseSuffixLinks.push_back(root->children[edgeID]);
                q.push(root->children[edgeID]);
            }
        }

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

            for(int edgeID = 0; edgeID < ALPHABET_SIZE; ++edgeID){
                if(node->children[edgeID] != NULL){
                    Trie* tempNode = node->suffixLink;
                    while(tempNode != root && tempNode->children[edgeID] == NULL){
                        tempNode = tempNode->suffixLink;
                    }
                    if(tempNode->children[edgeID] == NULL){
                        node->children[edgeID]->suffixLink = root;
                        root->reverseSuffixLinks.push_back(node->children[edgeID]);
                    }else{
                        node->children[edgeID]->suffixLink = tempNode->children[edgeID];
                        tempNode->children[edgeID]->reverseSuffixLinks.push_back(node->children[edgeID]);
                    }
                    q.push(node->children[edgeID]);
                }
            }
        }
    }

    void matchAllWords(const string& TEXT){
        Trie* root = this;
        Trie* node = root;
        for(char c: TEXT){
            int edgeID = c - FIRST_ELEM;
            while(node != NULL && node->children[edgeID] == NULL){
                node = node->suffixLink;
            }
            if(node == NULL){
                node = root;
            }else{
                node = node->children[edgeID];
            }
            node->matchCount += 1;
        }
    }

    void updateMatchCounts(){
        updateMatchCounts(this);
    }

    int getMatchCount(const string& WORD){
        Trie* node = this;
        for(char c: WORD){
            int edgeID = c - FIRST_ELEM;
            if(node->children[edgeID] == NULL){
                return 0;
            }
            node = node->children[edgeID];
        }
        return node->matchCount;
    }
};

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

    string s;
    cin >> s;

    int n;
    cin >> n;

    vector<string> words(n);
    for(int i = 0; i < n; ++i){
        cin >> words[i];
    }

    Trie trie;
    trie.insertAllWords(words);
    trie.createSuffixLinks();
    trie.matchAllWords(s);
    trie.updateMatchCounts();

    for(int i = 0; i < n; ++i){
        cout << trie.getMatchCount(words[i]) << "\n";
    }

    cin.close();
    cout.close();
    return 0;
}