Cod sursa(job #3228645)

Utilizator VladNANegoita Vlad-Andrei VladNA Data 9 mai 2024 16:59:14
Problema Aho-Corasick Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.23 kb
#include <bits/stdc++.h>
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("sse,avx,fma,avx2,bmi,bmi2,lzcnt,popcnt")

using namespace std;
using ll = long long;
using ld = long double;

struct node {
  unordered_map<char, node *> forward;
  node *suffix = NULL, *output = NULL;
  bool terminal = false;
  int word_index;

  void insert(string &p, int wi, int index) {
    if (index == p.size()) {
      terminal = true, word_index = wi;
      return;
    }

    if (!forward.count(p[index]))
      forward[p[index]] = new node;

    forward[p[index]]->insert(p, wi, index + 1);
  }

  // assume this is called on root
  void compute_suffix_links() {
    queue<node *> q;
    for (auto [c, neigh] : forward)
      q.push(neigh), neigh->suffix = this;

    while (!q.empty()) {
      auto curr = q.front();
      q.pop();

      for (auto [c, neigh] : curr->forward) {
        q.push(neigh);
        auto try_suff = curr->suffix;
        while (try_suff != this && try_suff->forward.count(c) == 0) {
          try_suff = try_suff->suffix;
        }

        neigh->suffix = (try_suff->forward.count(c) ? try_suff->forward[c] : this);
        neigh->output = (neigh->suffix->terminal ? neigh->suffix : neigh->suffix->output);
      }
    }
  }

  node *next_node(char c) {
    if (forward.count(c))
      return forward[c];

    if (suffix == NULL)
      return this;

    return suffix->next_node(c);
  }

  void count_occurences(vector<int> &v) {
    if (terminal)
      ++v[word_index];

    if (output)
      output->count_occurences(v);
  }

  ~node() {
    for (auto [_, neigh] : forward)
      delete neigh;
  }
};

void solve() {
  string text;
  int n;

  cin >> text >> n;
  vector<string> patterns(n);
  for (auto &p : patterns)
    cin >> p;

  auto root = new node;
  for (int i = 0; i < n; ++i)
    root->insert(patterns[i], i, 0);
  root->compute_suffix_links();

  vector<int> ans(n, 0);
  auto curr = root;
  for (char c : text) {
    curr = curr->next_node(c);
    curr->count_occurences(ans);
  }

  delete root;
  for (auto x : ans)
    cout << x << '\n';
}

int main() {
#ifndef ONLINE_JUDGE
  freopen("ahocorasick.in", "r", stdin);
  freopen("ahocorasick.out", "w", stdout);
#endif
  int t = 1;
  // cin >> t;
  while (t--)
    solve();

  return 0;
}