Cod sursa(job #3235050)

Utilizator RolandPetreanPetrean Roland RolandPetrean Data 13 iunie 2024 18:27:56
Problema Aho-Corasick Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.17 kb
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
// #define int ll

#define endl '\n'
#define pb push_back
using pi = array<int, 2>;

const int SIGMA = 26;
struct Node {
  bool vis = false;
  int parent_ch = -1, appeared = 0;
  vector<int> exit_ids;
  
  Node *parent = nullptr, *link = nullptr;
  vector<Node*> rev_links;
  array<Node*, SIGMA> ch{};
  
  Node(Node *parent, int parent_ch) {
    this->parent = parent;
    this->parent_ch = parent_ch;
  }
  Node() { // root
    link = this;
    for (int i = 0; i < SIGMA; ++i) {
      ch[i] = new Node(this, i);
      ch[i]->link = this;
    }
  }
  
  void add(int id, string& s, int ptr = 0) {
    if (ptr == (int)s.size()) {
      exit_ids.pb(id);
      return;
    }
    
    int idx = s[ptr] - 'a';
    if (ch[idx] == nullptr) {
      ch[idx] = new Node(this, idx);
    }
    ch[idx]->add(id, s, ptr + 1);
  }
  
  void compute_links() {
    if (link == nullptr) {
      link = parent->link;
      while (link->ch[parent_ch] == nullptr) {
        link->compute_links();
        link = link->link;
      }
      link = link->ch[parent_ch];
    }
    link->rev_links.pb(this);
    
    for (auto node : ch) {
      if (node == nullptr) continue;
      node->compute_links();
    }
  }
  
  void dfs(vector<int>& ans) {
    if (vis) return;
    vis = true;
    
    for (auto node : rev_links) {
      node->dfs(ans);
    }
    link->appeared += appeared;
    for (auto node : ch) {
      if (node == nullptr) continue;
      node->dfs(ans);
    }
    
    for (int i : exit_ids) {
      ans[i] = appeared;
    }
  }
};

int32_t main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  
  ifstream cin("ahocorasick.in");
  ofstream cout("ahocorasick.out");
  
  string a;
  int n;
  cin >> a >> n;
  
  Node aho;
  for (int i = 0; i < n; ++i) {
    string s;
    cin >> s;
    aho.add(i, s);
  }
  aho.compute_links();
  
  Node* node = &aho;
  for (int i = 0; i < (int)a.size(); ++i) {
    int idx = a[i] - 'a';
    while (node->ch[idx] == nullptr) {
      node = node->link;
    }
    node = node->ch[idx];
    
    ++node->appeared;
  }
  
  vector<int> ans(n);
  aho.dfs(ans);
  for (int i = 0; i < n; ++i) {
    cout << ans[i] << endl;
  }
}