Cod sursa(job #2487424)

Utilizator Robert_VRVRobert Vadastreanu Robert_VRV Data 4 noiembrie 2019 19:19:16
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.34 kb
#include <algorithm>
#include <fstream>
#include <queue>
#include <string.h>
#include <vector>

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

const int SIGMA = 26;
const int MAX_N = 100;

struct Trie {
  int nrf;
  int nrc;
  Trie* children[SIGMA];
  Trie* fail;
  int nr;
  Trie() {
    nrf = 0;
    nrc = 0;
    for (int i = 0; i < SIGMA; i++)
      children[i] = NULL;
    fail = NULL;
  }
};

int numNodes;
Trie* nodes[5 + MAX_N];

void insert(Trie* nod, char* s) {
  if (s[0] == '\0') {
    nod->nrc++;
    nodes[++numNodes] = nod;
  } else {
    if (nod->children[s[0] - 'a'] == NULL) {
      nod->nrf++;
      nod->children[s[0] - 'a'] = new Trie;
    }
    insert(nod->children[s[0] - 'a'], s + 1);
  }
}

const int MAX_SIZE = 1000000;
const int MAX_D = 1000;

char T[5 + MAX_SIZE];

std::vector<Trie*> bfs;

void antiBFS() {
  std::reverse(bfs.begin(), bfs.end());
  for (Trie *nod : bfs)
    nod->fail->nr += nod->nr;
}

int main() {

  fin >> T;
  Trie *root = new Trie;
  int n;
  fin >> n;
  for (int i = 1; i <= n; i++) {
    char s[5 + MAX_D];
    fin >> s;
    insert(root, s);
  }
  std::queue<Trie*> q;
  root->fail = NULL;
  for (int i = 0; i < SIGMA; i++) {
    if (root->children[i] != NULL) {
      root->children[i]->fail = root;
      q.push(root->children[i]);
    }
  }
  while (!q.empty()) {
    Trie* parent = q.front();
    q.pop();
    for (int i = 0; i < SIGMA; i++) {
      if (parent->children[i] != NULL) {
        Trie* child = parent->children[i];
        q.push(child);
        bfs.push_back(child);
        Trie* aux = parent->fail;
        while (aux != root && aux->children[i] == NULL)
          aux = aux->fail;
        if (aux->children[i] != NULL)
          child->fail = aux->children[i];
        else
          child->fail = root;
      }
    }
  }
  int sizeT = strlen(T);
  Trie* current = root;
  for (int i = 0; i < sizeT; i++) {
    while (current != root && current->children[T[i] - 'a'] == NULL)
      current = current->fail;
    if (current->children[T[i] - 'a'] != NULL)
      current = current->children[T[i] - 'a'];
    else
      current = root;
    if (current != root)
      current->nr++;
  }
  antiBFS();
  for (int i = 1; i <= n; i++)
    fout << nodes[i]->nr << '\n';



  return 0;
}