Cod sursa(job #2265192)

Utilizator MiricaMateiMirica Matei MiricaMatei Data 20 octombrie 2018 18:39:56
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.13 kb
#include <bits/stdc++.h>

using namespace std;

const int MAXK = 100;
const int MAXN = 1000000;
const int MAXM = 10000;
const int SIGMA = 26;

struct Node {
  Node* fail;
  Node* son[SIGMA + 5];
  int fr;
  vector<int>word;

  Node() {
    fr = 0;
    fail = NULL;
    for (int i = 0; i < SIGMA; ++i)
      son[i] = NULL;
  }

  void add(char *s, int index) {
    if ('a' > *s || 'z' < *s) {
      word.push_back(index);
      return ;
    }
    int aux = *s - 'a';
    if (son[aux] == NULL)
      son[aux] = new Node;
    son[aux]->add(s + 1, index);
  }

  void get(char* s) {
    if ('a' > *s || 'z' < *s)
      return ;
    int aux = *s - 'a';
    if (son[aux] == NULL && fail != NULL)
      fail->get(s);
    else {
      if (son[aux] != NULL) {
        son[aux]->fr++;
        son[aux]->get(s + 1);
      } else {
        this->get(s + 1);
      }
    }
  }
};

char s[MAXN + 5];
char c[MAXN + 5];

int ans[MAXK + 5];

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

  scanf("%s", s);
  int n;
  scanf("%d ", &n);
  Node* t = new Node;
  for (int i = 1; i <= n; ++i) {
    scanf("%s", c);
    t->add(c, i);
  }

  queue<Node*>q;
  vector<Node*>v;

  for (int i = 0; i < SIGMA; ++i)
    if (t->son[i] != NULL) {
      t->son[i]->fail = t;
      q.push(t->son[i]);
    }


  while (!q.empty()) {
    Node* aux = q.front();
    q.pop();
    v.push_back(aux);
    for (int i = 0; i < SIGMA; ++i) {
      if (aux->son[i] != NULL) {
        aux->son[i]->fail = aux;
        do {
          aux->son[i]->fail = aux->son[i]->fail->fail;
        } while (aux->son[i]->fail != t && aux->son[i]->fail->son[i] == NULL);
        if (aux->son[i]->fail->son[i] != NULL)
          aux->son[i]->fail = aux->son[i]->fail->son[i];
        q.push(aux->son[i]);
      }
    }
  }

  t->get(s);

  reverse(v.begin(), v.end());

  for (auto it:v) {
    Node* aux = it;
    aux->fail->fr += aux->fr;
    for (auto it1:aux->word)
      ans[it1] += aux->fr;
  }

  for (int i = 1; i <= n; ++i)
    printf("%d\n", ans[i]);

  return 0;
}