Cod sursa(job #2766945)

Utilizator lahayonTester lahayon Data 3 august 2021 23:59:02
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.03 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <algorithm>

using namespace std;

const int ALPHA_SZ = 26;

struct Aho{
    Aho* children[ALPHA_SZ];
    Aho* failLink;
    vector<int> words;
    int cnt;
    Aho(){
        cnt = 0;
        failLink = nullptr;
        words = {};
        for(int i = 0; i < ALPHA_SZ; ++i)
            children[i] = nullptr;
    }
};

Aho* AHC = new Aho();

void insert(Aho* node, int pos, const int& id, const vector<string>& patterns){
    if(pos == patterns[id].size()){
        node->words.push_back(id);
        return;
    }

    if(node->children[patterns[id][pos] - 'a'] == nullptr)
        node->children[patterns[id][pos] - 'a'] = new Aho();
    insert(node->children[patterns[id][pos] - 'a'], pos + 1, id, patterns);
}

void BFS(){
    
    AHC->failLink = AHC;
    queue<Aho*> Q;
    for(int i = 0; i < ALPHA_SZ; ++i)
        if(AHC->children[i] != nullptr){
            AHC->children[i]->failLink = AHC;
            Q.push(AHC->children[i]);
        }
    while(!Q.empty()){
        Aho* curr = Q.front(); Q.pop();
        for(int i = 0; i < ALPHA_SZ; ++i)
            if(curr->children[i] != nullptr){
                Aho* fail = curr->failLink;
                while(fail != AHC && fail->children[i] == nullptr)
                    fail = fail->failLink;
                if(fail->children[i] != nullptr && fail->children[i] != curr->children[i])
                    fail = fail->children[i];

                curr->children[i]->failLink = fail;
                Q.push(curr->children[i]);
            }
    }
}

vector<int> solve(const int& N, const string& text){

    vector<int> freq(N);
    Aho* head = AHC;
    for(int i = 0; i < text.size(); ++i){

        while(head != AHC && head->children[text[i] - 'a'] == nullptr)
            head = head->failLink;
        if(head->children[text[i] - 'a'] != nullptr)
            head = head->children[text[i] - 'a'];
        
        ++head->cnt;
    }

    queue<Aho*> Q;
    vector<Aho*> nodes;
    Q.push(AHC);
    
    while(!Q.empty()){
        Aho* curr = Q.front(); Q.pop();
        nodes.push_back(curr);
        for(int i = 0; i < ALPHA_SZ; ++i)
            if(curr->children[i] != nullptr)
                Q.push(curr->children[i]);
    }

    reverse(nodes.begin(), nodes.end());
    for(Aho* node : nodes){
        for(auto id : node->words)
            freq[id] += node->cnt;
        node->failLink->cnt += node->cnt;
    }
    return freq;
}

int main()
{

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

    cin.tie(nullptr)->sync_with_stdio(false);

    string text; cin >> text;
    int N; cin >> N;
    vector<string> patterns(N);
    for(int i = 0; i < N; ++i){
        cin >> patterns[i];
        insert(AHC, 0, i, patterns);
    }

    BFS();
    vector<int> res = solve(N, text);
    for(auto r : res)
        cout << r << "\n";

    cin.close();
    cout.close();

    return 0;
}