Cod sursa(job #2522141)

Utilizator IulianOleniucIulian Oleniuc IulianOleniuc Data 12 ianuarie 2020 00:40:29
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.6 kb
#include <bits/stdc++.h>
using namespace std;

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

class Trie {
  private:
    struct Node {
        int exit, link, father;
        char letter;
        int next[26], tran[26];
        vector<int> ends;

        Node(int father = -1, char letter = '*') : father(father), letter(letter) {
            exit = -1;
            link = -1;
            memset(next, -1, sizeof(next));
            memset(tran, -1, sizeof(tran));
        }
    };

    int n;
    vector<Node> trie;

  public:
    Trie() : n(0), trie(1) {
        trie[0].exit = 0;
    }

    void insert(string& str);
    void lazy(int node);
    vector<int> count(string& str);

    int getLink(int node);
    int getTran(int node, char chr);
};

void Trie::insert(string& str) {
    int node = 0;
    for (char chr : str) {
        int code = chr - 'a';
        if (trie[node].next[code] == -1) {
            trie[node].next[code] = trie.size();
            trie.emplace_back(node, chr);
        }
        node = trie[node].next[code];
    }
    trie[node].ends.push_back(n++);
}

int Trie::getLink(int node) {
    if (trie[node].link == -1) {
        if (!node || !trie[node].father)
            trie[node].link = 0;
        else
            trie[node].link = getTran(getLink(trie[node].father), trie[node].letter);
    }
    return trie[node].link;
}

int Trie::getTran(int node, char chr) {
    int code = chr - 'a';
    if (trie[node].tran[code] == -1) {
        if (trie[node].next[code] != -1)
            trie[node].tran[code] = trie[node].next[code];
        else
            trie[node].tran[code] = (node ? getTran(getLink(node), chr) : 0);
    }
    return trie[node].tran[code];
}

void Trie::lazy(int node) {
    if (trie[node].exit != -1)
        return;
    lazy(getLink(node));
    trie[node].exit = (trie[getLink(node)].ends.empty() ? trie[getLink(node)].exit : getLink(node));
}

vector<int> Trie::count(string& str) {
    vector<int> cnt(n);
    int node = 0;
    for (char chr : str) {
        node = getTran(node, chr);
        lazy(node);
        int temp = node;
        while (temp) {
            for (int it : trie[temp].ends)
                cnt[it]++;
            temp = trie[temp].exit;
        }
    }
    return cnt;
}

int main() {
    string str; fin >> str;
    int n; fin >> n;

    Trie trie;
    for (int i = 0; i < n; i++) {
        string s; fin >> s;
        trie.insert(s);
    }

    auto sol = trie.count(str);
    for (int i = 0; i < n; i++)
        fout << sol[i] << '\n';
    return 0;
}