Cod sursa(job #2043327)

Utilizator algebristulFilip Berila algebristul Data 19 octombrie 2017 21:28:43
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.71 kb
#include <bits/stdc++.h>

using namespace std;

struct Trie;

Trie *root;

struct Trie {
  Trie *nxt[26];
  Trie *fail;
  int cnt;
  vector<Trie*> bl;
  
  Trie() {
    for (int i = 0; i < 26; i++) nxt[i] = nullptr;
    fail = nullptr;
    cnt = 0;
  }
  
  Trie* add(const char* s) {
    if (!*s) return this;
    
    auto& n = nxt[*s - 'a'];
    if (n == nullptr) n = new Trie;
    return n->add(s + 1);
  }
  
  Trie* next(char c) {
    Trie* tmp = this;
    
    while (tmp && tmp->nxt[c - 'a'] == nullptr) tmp = tmp->fail;
    if (!tmp) return root;
    return tmp->nxt[c - 'a'];
  }
};

void backlinks() {
  queue<Trie*> q;
  q.push(root);
  
  while (!q.empty()) {
    auto* crt = q.front();
    q.pop();
    
    for (char c = 'a'; c <= 'z'; c++) {
      if (crt->nxt[c - 'a'] == nullptr) continue;
      auto* nextFail = crt->fail ? crt->fail->next(c) : root;
      crt->nxt[c - 'a']->fail = nextFail;
      nextFail->bl.push_back(crt->nxt[c - 'a']);
      q.push(crt->nxt[c - 'a']);
    }
  }
}

void df() {
  std::function<void (Trie*)> internal_df = [&](Trie* x) {
    for (auto* y : x->bl) {
      internal_df(y);
      x->cnt += y->cnt;
    }
  };
  
  internal_df(root);
}

Trie* words[105];
char S[1000005];
char w[10005];
int n;

int main() {
  freopen("ahocorasick.in", "r", stdin);
  freopen("ahocorasick.out", "w", stdout);
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  
  root = new Trie;
  cin >> (S + 1);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> w;
    words[i] = root->add(w);
  }
  
  backlinks();
  Trie *crt = root;
  for (int i = 1; S[i]; i++) {
    crt = crt->next(S[i]);
    crt->cnt++;
  }
  
  df();
  
  for (int i = 1; i <= n; i++) {
    cout << words[i]->cnt << '\n';
  }

  return 0;
}