Cod sursa(job #2849296)

Utilizator BalasaRaduBalasa Radu BalasaRadu Data 14 februarie 2022 20:26:51
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.56 kb
#include <bits/stdc++.h>
using namespace std;

ifstream fin("ahocorasick.in");
ofstream fout("ahocorasick.out");

const int SIGMA=26,dim=109;

struct Trie{
    int index,dp;
    Trie *children[SIGMA];
    Trie *failLink;
    Trie *outputLink;
    Trie(){
        index=-1;
        dp=0;
        for(int i=0;i<SIGMA;i++){
            children[i]=NULL;
        }
        failLink=NULL;
    }
};

string A,s;
vector<Trie*>order;
Trie* ptr[dim];

void Insert(Trie* root,int p,int index){
    if(p==s.size()){
        root->index=index;
        ptr[index]=root;
        return;
    }
    int c=s[p]-'a';
    if(!root->children[c]){
        root->children[c]=new Trie;
    }
    Insert(root->children[c],p+1,index);
}

void ahoCorasick(Trie* root){
    root->failLink=root->outputLink=root;
    queue<Trie*>q;
    for(int i=0;i<SIGMA;i++){
        if(root->children[i]!=NULL){
            Trie* t=root->children[i];
            t->failLink=root;
            t->outputLink=root;
            q.push(t);
        }
    }
    order.push_back(root);
    while(!q.empty()){
        Trie* u=q.front();
        q.pop();
        order.push_back(u);
        for(int i=0;i<SIGMA;i++){
            if(u->children[i]!=NULL){
                Trie* v=u->children[i];
                Trie* tmp=u->failLink;
                while(tmp->children[i]==NULL&&tmp!=root){
                    tmp=tmp->failLink;
                }
                if(tmp->children[i]!=NULL){
                    v->failLink=tmp->children[i];
                }
                else{
                    v->failLink=root;
                }
                if (v->failLink->index!=-1) {
                  v->outputLink=v->failLink;
                } else {
                  v->outputLink=v->failLink->outputLink;
                }
                q.push(v);
            }
        }
    }
}

void makeCount(Trie* root){
    Trie* u=root;
    int len=A.size();
    for(int i=0;i<len;i++){
        int c=A[i]-'a';
        while(!u->children[c]&&u!=root){
            u=u->failLink;
        }
        if(u->children[c]){
            u=u->children[c];
        }
        u->dp+=1;
    }
    reverse(order.begin(),order.end());
    for(auto it:order){
        it->outputLink->dp+=it->dp;
    }
}

int main(){
    int n;
        fin>>A;
        fin>>n;
    Trie* root=new Trie;
    for(int i=0;i<n;i++){
        fin>>s;
        Insert(root,0,i);
    }
    ahoCorasick(root);
    makeCount(root);
    for(int i=0;i<n;i++){
        fout<<ptr[i]->dp<<'\n';
    }
}