Cod sursa(job #2468413)

Utilizator Briana_NeaguNeagu Briana Briana_Neagu Data 5 octombrie 2019 15:18:19
Problema Aho-Corasick Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.17 kb
#include <bits/stdc++.h>
#define nmax 1000005

using namespace std;

ifstream f("ahocorasick.in");
ofstream g("ahocorasick.out");

struct trie
{
    trie *next[26];
    trie *suf;
    int fv;
    trie()
    {
        this -> suf = NULL;
        this -> fv = 0;
        memset(this -> next, NULL, sizeof(this -> next));
    }
};

trie *root = new trie();
trie* ans[nmax];
void add(trie *nod, string &c, const int index, int i, const int len)
{
    if (i == len)
    {
        ans[index] = nod;
        return;
    }
    int next_letter = c[i] - 'a';
    if (nod -> next[next_letter] == nullptr)
        nod -> next[next_letter] = new trie();

    add(nod -> next[next_letter], c, index, i + 1, len);
}

vector <trie*> fin;
void create_links()
{
    queue <trie*> coada;
    coada.push(root);
    while (!coada.empty())
    {
        trie *nod = coada.front();
        coada.pop();
        for (int i = 0; i < 26; ++ i)
            if (nod -> next[i] != nullptr)
            {
                trie *now, *sufix;
                now =  nod -> next[i];
                sufix =  nod -> suf;
                fin.push_back(now);
                while (sufix != root && sufix -> next[i] == nullptr)
                    sufix = sufix -> suf;
                if (sufix -> next[i] != nullptr && sufix -> next[i] != now) // primul nivel
                    now -> suf = sufix -> next[i];
                else
                    now -> suf = root;
                coada.push(now);
            }
    }
}

void antibfs()
{
  for (int i = fin.size() - 1; i >= 0; i --)
      fin[i] -> suf -> fv += fin[i] -> fv;
}

int main()
{
  string s;
  f >> s;
  int n;
  f >> n;
  root -> suf = root;
  for (int i = 1; i <= n; ++ i)
  {
      string c;
      f >> c;
      int len = c.length();
      add(root, c, i, 0, len);
  }
  create_links();
  trie *aux = root;
  for (auto c : s)
  {
      int next_letter = c - 'a';
      while (aux != root && aux -> next[next_letter] == nullptr)
          aux = aux -> suf;
      if (aux -> next[next_letter] != nullptr) // nu e radacina
      {
          aux = aux -> next[next_letter];
          aux -> fv ++;
      }
  }

  antibfs();
  for (int i = 1; i <= n; ++ i)
      g << ans[i] -> fv << '\n';

}