Cod sursa(job #1981550)

Utilizator algebristulFilip Berila algebristul Data 15 mai 2017 23:11:50
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.95 kb
#include <bits/stdc++.h>

using namespace std;

constexpr int nmax = 1000005;
constexpr int sigma = 26;

char B[nmax];
char A[nmax];
int num, n, m, cnt;

struct AC {
  AC *next[sigma];
  AC *fail;
  vector<AC *> v;
  int cnt;

  AC() : cnt(0) {
    for (int i = 0; i < sigma; i++) {
      next[i] = nullptr;
    }
    fail = nullptr;
  }

  int ord(char c) {
    assert(c >= 'a' && c <= 'z');
    return c - 'a';
  }

  AC *add(const char *S) {
    if (*S == 0) {
      return this;
    }

    int x = ord(*S);
    if (next[x] == nullptr) {
      next[x] = new AC;
    }

    return next[x]->add(S + 1);
  }

  AC *nextNode(char c, AC *root) {
    int x = ord(c);
    AC *tmp = this;

    while (tmp && tmp->next[x] == nullptr) tmp = tmp->fail;
    if (!tmp) return root;
    return tmp->next[x];
  }
};

void backlinks(AC *root) {
  queue<AC *> q;
  q.push(root);
  while (!q.empty()) {
    AC *front = q.front();
    q.pop();

    for (int i = 0; i < sigma; i++) {
      if (front->next[i] == nullptr) continue;
      AC *tmp = front->fail;
      while (tmp && tmp->next[i] == nullptr) {
        tmp = tmp->fail;
      }

      if (tmp == nullptr) {
        front->next[i]->fail = root;
        root->v.push_back(front->next[i]);
      } else {
        front->next[i]->fail = tmp->next[i];
        tmp->next[i]->v.push_back(front->next[i]);
      }

      q.push(front->next[i]);
    }
  }
}

void df(AC *x) {
  for (AC *y : x->v) {
    df(y);
    x->cnt += y->cnt;
  }
}

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

  scanf("%s", B);
  scanf("%d", &num);
  m = strlen(B);
  AC *ac = new AC;

  vector<AC *> words(num, nullptr);

  for (int i = 0; i < num; i++) {
    scanf("%s", A);
    words[i] = ac->add(A);
  }

  backlinks(ac);

  AC *tmp = ac;
  for (int i = 0; i < m; i++) {
    tmp = tmp->nextNode(B[i], ac);
    tmp->cnt++;
  }

  df(ac);

  for (int i = 0; i < num; i++) {
    printf("%d\n", words[i]->cnt);
  }

  return 0;
}