Cod sursa(job #2684564)

Utilizator victorzarzuZarzu Victor victorzarzu Data 14 decembrie 2020 08:30:52
Problema Aho-Corasick Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.81 kb
#include <bits/stdc++.h>
#define dic_size 26
 
using namespace std;
char a[1000000], t[10000];
int n, rez[10005], st, sf;
 
struct Trie
{
  int nr;
  vector<int> siruri;
  Trie *fiu[dic_size], *fail;
 
  Trie()
  {
    nr = 0;
    fail = NULL;
    memset(fiu, 0, sizeof(fiu));
  }
};
 
Trie *T = new Trie, *U = new Trie;
Trie *q[10000 * 10000 + 5];
 
void insert(Trie *nod, char *s, int index)
{
  if(!(*s))
    {
      nod -> siruri.push_back(index);
      return;
    }
  int urm = s[0] - 'a';
  if(!(nod -> fiu[urm]))
    nod -> fiu[urm] = new Trie;
  insert(nod -> fiu[urm], s + 1, index);
}
 
void compute()
{
  Trie *top, *fa;
  T -> fail = T;
  
  for(q[st = sf = 1] = T;st <= sf;++st)
  {
    top = q[st];
    
    for(short ch = 0;ch < dic_size;++ch)
      if(top -> fiu[ch])
      {
        for(fa = top -> fail;fa != T && !fa -> fiu[ch];fa = fa -> fail);
        if(fa -> fiu[ch] && fa -> fiu[ch] != top -> fiu[ch]) fa = fa -> fiu[ch];
        top -> fiu[ch] -> fail = fa;
        q[++sf] = top -> fiu[ch];
      }   
  }
  T -> fail = NULL;
} 
void Read()
{
  freopen("ahocorasick.in", "r", stdin);
  freopen("ahocorasick.out", "w", stdout);
  scanf("%s", a), scanf("%d", &n);
  for(int i = 1;i <= n;++i)
    scanf("%s", t), insert(T, t, i);
}
 
void reverse()
{
  Trie *top;
  for(int i = sf;i > 0;--i)
  {
    top = q[i];
    if(top -> fail) top -> fail -> nr += top -> nr;
    for(int j = 0;j < top -> siruri.size();++j)
      rez[top -> siruri[j]] = top -> nr;
  }
}
 
void Solve()
{
  compute();
  int len = strlen(a); U = T;
  for(int i = 0;i < len;++i)
    {
      int urm = a[i] - 'a';
      for(;!U -> fiu[urm] && U != T;U = U -> fail);
      if(U -> fiu[urm])
        U = U -> fiu[urm];
      U -> nr++;
    }
  reverse();
  for(int i = 1;i <= n;++i)
    printf("%d\n", rez[i]);
}
 
int main()
{
  Read();
  Solve();
  return 0;
}