Cod sursa(job #3250405)

Utilizator MikeStrikeAgache Mihai MikeStrike Data 20 octombrie 2024 17:32:30
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.34 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <cstring>

using namespace std;

const int MAXC = 26;
ifstream in ("ahocorasick.in");
ofstream out ("ahocorasick.out");
    
    
struct TrieNode {
    unordered_map<char, TrieNode*> children; 
    TrieNode* fail; 
    vector<int> output; 

    TrieNode() : fail(nullptr) {}
};

struct AhoCorasick {
    TrieNode* root;
    vector<int> keywordCount;

    AhoCorasick() {
        root = new TrieNode();
    }


    void insert(const string &word, int index) {
        TrieNode* current = root;
        for (char ch : word) {
            if (current->children.find(ch) == current->children.end()) {
                current->children[ch] = new TrieNode();
            }
            current = current->children[ch];
        }
        current->output.push_back(index);
    }

  
    void buildFailureLinks() {
        queue<TrieNode*> q;
        root->fail = root; 


        for (auto &child : root->children) {
            child.second->fail = root;
            q.push(child.second);
        }

   
        while (!q.empty()) {
            TrieNode* current = q.front();
            q.pop();

    
            for (auto &child : current->children) {
                char ch = child.first;
                TrieNode* nextNode = child.second;

               
                TrieNode* failState = current->fail;
                while (failState != root && failState->children.find(ch) == failState->children.end()) {
                    failState = failState->fail;
                }
                if (failState->children.find(ch) != failState->children.end()) {
                    nextNode->fail = failState->children[ch];
                } else {
                    nextNode->fail = root;
                }

              
                nextNode->output.insert(nextNode->output.end(), nextNode->fail->output.begin(), nextNode->fail->output.end());
                
                q.push(nextNode); 
            }
        }
    }


    void search(const string &text) {
        TrieNode* current = root;
        for (int i = 0; i < text.size(); ++i) {
            char ch = text[i];

        
            while (current != root && current->children.find(ch) == current->children.end()) {
                current = current->fail;
            }

    
            if (current->children.find(ch) != current->children.end()) {
                current = current->children[ch];
            }

            
            for (int wordIndex : current->output) {
                keywordCount[wordIndex]++;
            }
        }
    }

    void processText(const string &text, const vector<string> &keywords) {
        keywordCount.assign(keywords.size(), 0); 


        for (int i = 0; i < keywords.size(); ++i) {
            insert(keywords[i], i);
        }


        buildFailureLinks();


        search(text);


        for (int i = 0; i < keywords.size(); ++i) {
            out << keywordCount[i] << endl;
        }
    }
};

int main() {
    
   
    string A;
    int n;
    in >> A >> n;

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

    AhoCorasick automaton;
    automaton.processText(A, words);

    return 0;
}