Cod sursa(job #2707971)

Utilizator mitocaru_marioMitocaru Mario-Alexandru mitocaru_mario Data 18 februarie 2021 08:33:52
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.82 kb
#include<bits/stdc++.h>
using namespace std;
ifstream f("ahocorasick.in");
ofstream g("ahocorasick.out");
struct nod
{
    vector<int> L;/// contine lista "literelor" pe care nu am "fail"
    int ap;/// numar aparitii pentru fiecare nod
    nod *S[26],*fail;/// link la succesori si fail
    nod()/// constructor
    {
        L.resize(0);
        ap=0;
        for(int i=0;i<26;i++)
            S[i]=NULL;
        fail=NULL;
    }
};
nod *root,*poz[101];
string P,W;
int n;
int main()
{
    root = new nod;
    f>>P>>n;
    /// se construieste trie cu cele n cuvinte
    for(int i=1;i<=n;i++)
    {
        f>>W;
        nod *p=root;
        for(auto it:W)
        {
            int k=it-'a';
            if(!p->S[k])
            {
                p->S[k] = new nod;
                p->L.push_back(k);
            }
            p=p->S[k];
        }
        /// se memoreaza pozitia unde se termina cuvantul in trie
        poz[i]=p;
    }


    /// se construieste fail pentru fiecare nod de trie
    vector<nod*>Q;
    int nr=0,baza=0;
    root->fail=root;/// pentru root fail=root
    /// totii fii radacinii au fail=root
    /// apoi toate nodurile se vor procesa nivel cu nivel
    for(auto k:root->L)
    {
        root->S[k]->fail=root;
        Q.push_back(root->S[k]);nr++;
    }
    while(baza<nr)
    {
        nod *X=Q[baza++];
        for(auto k:X->L)
        {
            /// pentru fiecare fiu procesat setez fail !!!
            /// plec de la fail-ul nodului curent
            /// merg din fail in fail pana cand pot pleca dintr-unul
            /// pe "litera" fiului procesat
            /// daca nu merge ajung in radacina si fiul va avea fail in radacina
            nod *failNow=X->fail;
            do
            {
                if(failNow->S[k]){X->S[k]->fail=failNow->S[k];break;}
                if(failNow==root){X->S[k]->fail=root;break;}
                failNow=failNow->fail;
            }
            while(1);
            /// dupa ce am setat fail la un fiu pun fiul in coada
            /// mai tarziu voi seta fail pentru fiii acestuia !!!
            Q.push_back(X->S[k]);nr++;
        }
    }


    /// se parcurge textul (P) si ori de cate ori o litera "pleaca"
    /// pe o directie buna merg acolo si cresc numarul de aparitii
    /// Daca pe un nod de trie nu pot pleca pe litera ma mut in fail si
    /// incerc de acolo.

    int m=P.size();
    nod *p=root;
    for(int i=0;i<m;)
    {
        int k=P[i]-'a';
        if(p->S[k])
        {
            p=p->S[k];
            p->ap++;
            i++;
        }
        else if(p==root)
            i++;
        else
            p=p->fail;
    }
    for(;Q.size();Q.pop_back())
        Q.back()->fail->ap+=Q.back()->ap;
    for(int i=1;i<=n;i++)
        g<<poz[i]->ap<<'\n';



}