Cod sursa(job #3304076)

Utilizator unomMirel Costel unom Data 20 iulie 2025 12:32:08
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.29 kb
#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;
}