Cod sursa(job #1554541)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 21 decembrie 2015 14:15:33
Problema Aho-Corasick Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.53 kb
#include <bits/stdc++.h>

using namespace std;

const int kMaxLen = (int) 1e6;
const int kMaxPatternLen = (int) 1e4;
const int kMaxPatterns = 100;
const int kSigma = 26;
const int BUFF_SIZE = 4096;

struct Trie {
  Trie *next[kSigma];
  Trie *failLink;
  int freq;
  Trie() {
    for (int i = 0; i < kSigma; i++) {
      next[i] = NULL;
    }
    failLink = NULL;
    freq = 0;
  }
};

Trie *root;

char word[kMaxLen + 1];
char pattern[kMaxPatternLen + 1];

Trie *endLink[kMaxPatterns];
Trie *Q[kMaxPatterns * kMaxPatternLen];
int qStart, qEnd;

inline Trie *newNode() {
  static Trie *buff;
  static int pos = BUFF_SIZE;
  if (pos == BUFF_SIZE) {
    buff = new Trie[BUFF_SIZE];
    pos = 0;
  }
  return &buff[pos++];
}

int main(void) {
  ifstream in("ahocorasick.in");
  ofstream out("ahocorasick.out");
  in.tie(0);
  ios_base::sync_with_stdio(0);
  int numPatterns;
  int stringLength;
  Trie *curr;

  root = new Trie;

  in >> word >> numPatterns;
  for (int i = 0; i < numPatterns; i++) {
    in >> pattern;
    stringLength = strlen(pattern);
    curr = root;
    for (int j = 0; j < stringLength; j++) {
      if (curr->next[pattern[j] - 'a'] == NULL) {
        curr->next[pattern[j] - 'a'] = newNode();
      }
      curr = curr->next[pattern[j] - 'a'];
    }
    endLink[i] = curr;
  }
  in.close();

  qStart = 0;
  qEnd = 0;
  root->failLink = root;
  for (int i = 0; i < kSigma; i++) {
    if (root->next[i] != NULL) {
      root->next[i]->failLink = root;
      Q[qEnd++] = root->next[i];
    }
  }
  while (qStart != qEnd) {
    curr = Q[qStart++];
    for (int i = 0; i < kSigma; i++) {
      if (curr->next[i] != NULL) {
        Trie *son = curr->next[i];
        Trie *tmp = curr->failLink;
        while (tmp->next[i] == NULL && tmp != root) {
          tmp = tmp->failLink;
        }
        if (tmp->next[i] != NULL) {
          son->failLink = tmp->next[i];
        } else {
          son->failLink = root;
        }
        Q[qEnd++] = son;
      }
    }
  }

  stringLength = strlen(word);
  curr = root;
  for (int i = 0; i < stringLength; i++) {
    while (curr->next[word[i] - 'a'] == NULL && curr != root) {
      curr = curr->failLink;
    }
    if (curr->next[word[i] - 'a']) {
      curr = curr->next[word[i] - 'a'];
    }
    curr->freq++;
  }

  for (int i = qEnd - 1; i >= 0; i--) {
    Q[i]->failLink->freq += Q[i]->freq;
  }

  for (int i = 0; i < numPatterns; i++) {
    out << endLink[i]->freq << '\n';
  }
  out.close();
  return 0;
}