Cod sursa(job #3304077)

Utilizator unomMirel Costel unom Data 20 iulie 2025 12:33:23
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.66 kb
/*#include <fstream>
#include <vector>
#include <queue>
#include <iostream>

using namespace std;

struct node
{
    node *fii[26];
    node *fail;
    vector<int> output;
};

ifstream in("ahocorasick.in");
ofstream out("ahocorasick.out");
int n;
string s, x;
node *root = new node();
int frec[105];

void adauga(string x, int ind)
{
    node *nod = root;

    for(auto it: x)
    {
        if(nod->fii[it - 'a'] == NULL)
        {
            nod->fii[it - 'a'] = new node();
        }

        nod = nod->fii[it - 'a'];
    }

    nod->output.push_back(ind);
}

void bfs()
{
    queue<node*> q;
    root->fail = root;
    for(int i = 0; i<26; i++)
    {
        if(root->fii[i] != NULL)
        {
            root->fii[i]->fail = root;
            q.push(root->fii[i]);
        }
    }

    while(!q.empty())
    {
        node *nod = q.front();
        q.pop();

        //cout<<"A";

        for(int i = 0; i<26; i++)
        {
            if(nod->fii[i] == NULL)
            {
                continue;
            }

            node *it = nod->fii[i];
            q.push(it);

            node *f = nod->fail;
            while(f != root && f->fii[i] == NULL)
            {
                f = f->fail;
            }

            if(f->fii[i] != NULL)
            {
                it->fail = f->fii[i];
            }
            else
            {
                it->fail = root;
            }

            for(auto ind: it->fail->output)
            {
                it->output.push_back(ind);
            }
        }
    }
}

int main()
{
    in>>s;

    in>>n;
    for(int i = 1; i<=n; i++)
    {
        in>>x;

        adauga(x, i);
    }

    bfs();

    int i = 0;
    node *nod = root;

    while(i < s.size())
    {
        if(nod->fii[s[i] - 'a'] != NULL)
        {
            nod = nod->fii[s[i] - 'a'];
            i++;

            for(auto it: nod->output)
            {
                frec[it]++;
            }
        }
        else
        {
            if(nod == root)
            {
                i++;
            }
            else
            {
                nod = nod->fail;
            }
        }
    }

    for(int i = 1; i<=n; i++)
    {
        out<<frec[i]<<'\n';
    }

    return 0;
}*/

//un test mai cct ultimul (solutia de mai sus ia 95)
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;

static const int MAXS = 1000000 + 5;
static const int ALPHA = 26;

int nxt[MAXS][ALPHA], fail[MAXS];
int node_cnt = 1;  // 0 = root
int endNode[105];  // starea în care se termină pattern-ul i
long long cntState[MAXS];

int main(){
    // I/O din fișiere și STDIO rapid
    freopen("ahocorasick.in","r",stdin);
    freopen("ahocorasick.out","w",stdout);
    static char A[1000005];
    int n;

    // Citim textul și numărul de pattern‑uri
    scanf("%s", A);
    scanf("%d", &n);

    // Construim trie‑ul și reținem endNode pentru fiecare pattern
    for(int id = 1; id <= n; id++){
        static char s[10005];
        scanf("%s", s);
        int u = 0;
        for(int i = 0; s[i]; i++){
            int c = s[i] - 'a';
            if(!nxt[u][c]) nxt[u][c] = node_cnt++;
            u = nxt[u][c];
        }
        endNode[id] = u;
    }

    // BFS pentru fail & completare tranziții, păstrăm ordinea în bfsOrd
    vector<int> bfsOrd;
    queue<int> q;
    // nivel 1
    for(int c = 0; c < ALPHA; c++){
        int v = nxt[0][c];
        if(v){
            fail[v] = 0;
            q.push(v);
            bfsOrd.push_back(v);
        }
    }
    while(!q.empty()){
        int u = q.front(); q.pop();
        for(int c = 0; c < ALPHA; c++){
            int v = nxt[u][c];
            if(v){
                int f = fail[u];
                while(f && !nxt[f][c]) f = fail[f];
                fail[v] = nxt[f][c];
                q.push(v);
                bfsOrd.push_back(v);
            } else {
                nxt[u][c] = nxt[ fail[u] ][c];
            }
        }
    }

    // Parcurgem textul și înregistrăm vizitele în cntState
    int cur = 0;
    for(int i = 0; A[i]; i++){
        int c = A[i] - 'a';
        cur = nxt[cur][c];
        cntState[cur]++;
    }

    // Propagăm înapoi pe fail, în ordinea inversă BFS
    for(int i = (int)bfsOrd.size()-1; i >= 0; --i){
        int u = bfsOrd[i];
        cntState[ fail[u] ] += cntState[u];
    }

    // Pentru fiecare pattern, răspunsul e cntState[endNode[id]]
    for(int id = 1; id <= n; id++){
        printf("%lld\n", cntState[ endNode[id] ]);
    }
    return 0;
}