Cod sursa(job #2446687)

Utilizator FunnyStockyMihnea Andreescu FunnyStocky Data 10 august 2019 14:14:36
Problema Aho-Corasick Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.3 kb
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>

using namespace std;

struct ac {
    int sol;
    vector <int> id;
    ac *kids[26], *link, *urm;

    ac() {
        sol = 0;
        urm = 0;
        link = 0;
        for(int j = 0; j < 26; j++)
            kids[j] = 0;
    }

};

ac *root = new ac;

void baga(string s, int id) {
    ac *now = root;
    for(auto &ch : s) {
        int c = ch - 'a';
        if(now->kids[c] == 0)
            now->kids[c] = new ac;
        now = now->kids[c];
    }
    now->id.push_back(id);
}

queue <ac*> q;

void calc_link() {
    q.push(root);
    root->urm = root;
    while(!q.empty()) {
        ac *now = q.front();
        q.pop();
        for(int j = 0; j < 26; j++) {
            ac *nou = now->kids[j];
            if(nou) {
                ac *t = now;
                nou->link = root;
                while(t != root) {
                    t = t->link;
                    if(t->kids[j]) {
                        nou->link = t->kids[j];
                        break;
                    }
                }
                if(nou->link->id.size())
                    nou->urm = nou->link;
                else
                    nou->urm = nou->link->urm;
                q.push(nou);
            }
        }
    }
}

int ans[107];

int main() {
    freopen("ahocorasick.in", "r", stdin);
    freopen("ahocorasick.out", "w", stdout);

    string pat;
    cin >> pat;
    int n;
    cin >> n;
    for(int j = 0; j < n; j++) {
        string s;
        cin >> s;
        baga(s, j + 1);
    }

    root->link = root;
    calc_link();

    ac *now = root;
    int pos = -1;
    for(auto &ch : pat) {
        pos++;
        int c = ch - 'a';
        int cntroot = 0;
        while(1) {
            if(now->kids[c]) {
                now = now->kids[c];
                break;
            } else {
                if(now == root)
                    break;
                now = now->link;
            }
        }
        ac *cur = now;
        while(cur != root) {
            for(auto &j : cur->id)
                ans[j]++;
            cur = cur->urm;
        }
    }

    for(int j = 1; j <= n; j++) {
        cout << ans[j] << "\n";
    }


    return 0;
}