Cod sursa(job #3308083)

Utilizator IleaIlea Bogdan Ilea Data 23 august 2025 13:04:28
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.6 kb
#include<iostream>
#include<queue>
#include<vector>
using namespace std;

#define CMAX 10001
#define NMAX 101
struct trie{
    trie*fiu[26],*backedge;
    int cnt=0;
    trie(){
        cnt=0;
        for(int i=0;i<26;++i){
            fiu[i]=nullptr;
        }
        backedge=nullptr;
    }
};
char str[CMAX];
vector<trie*>nods;
trie*root=new trie(),*cuvinte[NMAX];
trie*insert(trie*nod,char*s){ // insert ca si intr-o trie normala
    if(*s=='\0'){
        return nod;
    }
    if(nod->fiu[*s-'a']==nullptr){
        nod->fiu[*s-'a']=new trie();
    }
    return insert(nod->fiu[*s-'a'],s+1);
}
void bfs(){ // formarea de noduri pe backedgeuri
    queue<trie*>Q;
    Q.push(root);
    while(!Q.empty()){
        trie*nod=Q.front();
        nods.push_back(nod);
        Q.pop();
        for(int i=0;i<26;++i){
            if(nod->fiu[i]!=nullptr){
                trie*backedge=nod->backedge;
                while(backedge!=nullptr&&backedge->fiu[i]==nullptr){ // parcurgearea pe backedge cat de mult se poate
                    backedge=backedge->backedge;
                }
                if(backedge==nullptr){
                    backedge=root;
                }else{
                    backedge=backedge->fiu[i];
                }
                nod->fiu[i]->backedge=backedge; // setarea backedgeului fiului in backedgeu corespunzator
                Q.push(nod->fiu[i]);
            }
        }
    }
}
void match(string word){ // matchingu de main word pe trie
    trie*nod=root;
    for(auto c:word){
        while(nod!=nullptr&&nod->fiu[c-'a']==nullptr){
            nod=nod->backedge;
        }
        if(nod==nullptr){
            nod=root;
        }else{
            nod=nod->fiu[c-'a'];
        }
        ++nod->cnt;
    }
}
void update(){ // actualizarea de 'pseudo-propagare' a cnt-ului in muchile de unde a provenit
    while(!nods.empty()){
        trie*nod=nods.back();
        nods.pop_back();
        if(nod->backedge!=nullptr){
            nod->backedge->cnt+=nod->cnt;
        }
    }
}
int main(){
    #ifdef LOCAL
    #else
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        cout.tie(nullptr);
    #endif
    freopen("ahocorasick.in","r",stdin);
    freopen("ahocorasick.out","w",stdout);
    string word;
    cin>>word;
    int n;
    cin>>n;
    for (int i=0;i<n;++i){
        cin>>str;
        cuvinte[i]=insert(root,str); // memorarea pointerilor de end a cuvintelor
    }
    bfs();
    match(word);
    update();
    for(int i=0;i<n;++i){
        cout<<cuvinte[i]->cnt<<"\n";
    }
    return 0;
}