Cod sursa(job #1980802)

Utilizator TincaMateiTinca Matei TincaMatei Data 14 mai 2017 00:12:44
Problema Aho-Corasick Scor 25
Compilator cpp Status done
Runda Arhiva educationala Marime 2.44 kb
#include <cstdio>
#include <ctype.h>

const int MAX_S1 = 100000;
const int SIGMA = 26;
const int MAX_SIR = 100;
const int MAX_S2 = 10000;
char sir1[MAX_S1];
char query[MAX_SIR][MAX_S2+1];

char nextch(FILE *fin) {
  char ch = fgetc(fin);
  while(ch == ' ')
    ch = fgetc(fin);
  return ch;
}

struct Aho {
  int fr;
  char papach;
  Aho* fiu[SIGMA];
  Aho *fail, *papa;
  Aho() {
    for(int i = 0; i < SIGMA; ++i)
      fiu[i] = NULL;
    fail = papa = NULL;
    fr = 0;
    papach = -1;
  }
};

Aho *queue[MAX_SIR * (MAX_S2+1)];
int st, dr;

void add(Aho *t, char *x) {
  if(*x != '\0') {
    char ch = (*x - 'a');
    if(t->fiu[ch] == NULL) {
      t->fiu[ch] = new Aho();
      t->fiu[ch]->papa = t;
      t->fiu[ch]->papach = ch;
    }
    add(t->fiu[ch], x + 1);
  }
}

int queryAho(Aho *t, char *x) {
  if(*x == '\0')
    return t->fr;
  else
    return queryAho(t->fiu[(*x - 'a')], x + 1);
}

void bfs(Aho *t) {
  st = dr = 0;
  queue[dr++] = t;
  t->fail = t;
  while(st < dr) {
    Aho *nod = queue[st++];
    for(int i = 0; i < SIGMA; ++i)
      if(nod->fiu[i] != NULL)
        queue[dr++] = nod->fiu[i];

    if(nod != t) {
      Aho *cursor = nod->papa->fail;
      char ch = nod->papach;
      while(cursor != t && cursor->fiu[ch] == NULL)
        cursor = cursor -> fail;
      if(cursor->fiu[ch] == NULL)
        nod->fail = t;
      else
        nod->fail = cursor->fiu[ch];
      if(nod->fail == nod)
        nod->fail = t;
    }
  }
}

void antibfs(Aho *x) { //in queue voi avea deja nodurile in ordine
  for(int i = dr - 1; i >= 0; --i) {
    Aho *nod = queue[i];
    nod->fail->fr += nod -> fr;
  }
}

int main() {
  int n, s1 = 0;
  char ch;
  Aho *x = new Aho(), *cursor;
  FILE *fin = fopen("ahocorasick.in", "r");
  ch = nextch(fin);
  while(isalpha(ch)) {
    sir1[s1++] = ch;
    ch = nextch(fin);
  }
  fscanf(fin, "%d", &n);
  ch = nextch(fin);
  for(int i = 0; i < n; ++i) {
    ch = nextch(fin);
    int s = 0;
    while(isalpha(ch)) {
      query[i][s++] = ch;
      ch = nextch(fin);
    }
    add(x, query[i]);
  }
  fclose(fin);

  bfs(x);

  cursor = x;
  for(int i = 0; i < s1; ++i) {
    ch = sir1[i] - 'a';
    while(cursor != x && cursor -> fiu[ch] == NULL)
      cursor = cursor -> fail;

    if(cursor -> fiu[ch] != NULL) {
      cursor = cursor -> fiu[ch];
      cursor -> fr++;
    }
  }
  antibfs(x);

  FILE *fout = fopen("ahocorasick.out", "w");
  for(int i = 0; i < n; ++i)
    fprintf(fout, "%d\n", queryAho(x, query[i]));
  fclose(fout);
  return 0;
}