Cod sursa(job #3276663)

Utilizator divadddDavid Curca divaddd Data 14 februarie 2025 01:15:09
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.22 kb
#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
using namespace std;
const int NMAX = 1e6+2;
const int KMAX = 102;
const int SIGMA = 26;
int n,k,ans[KMAX];
string str,dict[KMAX];

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

struct ACNode {
  vector<int> occur;
  ACNode *children[SIGMA], *suffix;
  string value = "";
} *root;

void trieInsert(ACNode *nod, string str, int idx, int depth = 0){
  if(depth == str.size()){
    nod->occur.push_back(idx);
    return ;
  }
  int son = str[depth]-'a';
  if(nod->children[son] == nullptr){
    nod->children[son] = new ACNode();
    // nod->children[son]->value = nod->value + str[depth];
  }
  trieInsert(nod->children[son], str, idx, depth+1);
}

int main() {
  fin >> str;
  n = str.size();
  fin >> k;
  root = new ACNode();
  for(int i = 1; i <= k; i++){
    fin >> dict[i];
    trieInsert(root, dict[i], i);
  }
  deque<ACNode *> dq;
  dq.push_back(root);
  while(!dq.empty()){
    auto nod = dq.back();
    if(nod->suffix == nullptr || nod->suffix == nod){
      nod->suffix = root;
    }
    // cout << "curr nod = " << nod->value << ", suffix = " << nod->suffix->value << "\n";
    nod->occur.insert(nod->occur.end(), all(nod->suffix->occur));
    dq.pop_back();
    for(int i = 0; i < SIGMA; i++){
      ACNode *child = nod->children[i];
      if(child != nullptr){
        dq.push_front(child);
        // cout << "calculating suffix for " << child->value << "\n";
        child->suffix = nod->suffix;
        while(child->suffix != root && child->suffix->children[i] == nullptr){
          // cout << "curr try = " << child->suffix->value << "\n";
          child->suffix = child->suffix->suffix;
        }
        child->suffix = child->suffix->children[i];
      }
    }
  }

  ACNode *currNode = root;
  for(int i = 0; i < n; i++){
    int ch = str[i]-'a';
    while(currNode != root && currNode->children[ch] == nullptr){
      currNode = currNode->suffix;
    }
    if(currNode->children[ch] != nullptr){
      currNode = currNode->children[ch];
    }
    for(int it: currNode->occur){
      ans[it]++;
    }
  }
  for(int i = 1; i <= k; i++){
    fout << ans[i] << "\n";
  }
  return 0;
}