Cod sursa(job #2231718)

Utilizator Stefan_RaduStefan Radu Stefan_Radu Data 15 august 2018 18:27:11
Problema Aho-Corasick Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.91 kb
#include <fstream>
#include <vector>
#include <string>
#include <queue>
#define L(x) x - 'a'

using namespace std;

const int MAX = 1e6 + 7;

ifstream cin ("ahocorasick.in");
ofstream cout ("ahocorasick.out");

class Aho {
public:

  Aho () {

    cin >> s;
    memIndex = 0;

    gr.resize (MAX);
    lvl.resize (MAX);
    tree.resize (MAX);

    cin >> n;
    ans.resize (n + 1);

    for (int i = 1; i <= n; ++ i) {

      string aux;
      cin >> aux;
      m_Insert (aux, i);
    }

    m_SetLinks ();
  }

  void Solve () {

    int curNode = 0;
    for (auto x : s) {

      if (not tree[curNode].letter[L (x)]) {

        while (curNode) {

          if (tree[curNode].letter[L (x)]) {
            break;
          }

          curNode = tree[curNode].suffLink;
        }
      }

      curNode = tree[curNode].letter[L (x)];
      ++ tree[curNode].frecv;
    }

    queue < int > q;
    for (int i = 1; i <= memIndex; ++ i) {
      if (not lvl[i]) {
        q.push (i);
      }
    }

    while (not q.empty ()) {

      curNode = q.front ();
      q.pop ();

      tree[tree[curNode].suffLink].frecv += tree[curNode].frecv;

      for (auto x : gr[curNode]) {
        if (--lvl[x] == 0) {
          q.push (x);
        }
      }
    }

    for (int i = 1; i <= memIndex; ++ i) {
      ans[tree[i].wordIndex] = tree[i].frecv;
    }

    for (int i = 1; i <= n; ++ i) {
      cout << ans[i] << '\n';
    }
  }

private:

  struct Node {

    Node () {

      frecv = 0;
      suffLink = 0;
      wordIndex = 0;

      for (int i = 0; i < 26; ++ i) {
        letter[i] = 0;
      }
    }

    int frecv, suffLink, wordIndex, letter[26];
  };

  string s;
  int n, memIndex;
  vector < Node > tree;
  vector < int > ans, lvl;
  vector < vector < int > > gr;
   
  void m_Insert (string &s, int wordIndex) {

    int curNode = 0;

    for (auto x : s) {

      if (not tree[curNode].letter[L (x)]) {
        tree[curNode].letter[L (x)] = ++ memIndex;

        ++ lvl[curNode];
        gr[memIndex].push_back (curNode);
      }

      curNode = tree[curNode].letter[L (x)];
    }

    tree[curNode].wordIndex = wordIndex;
  }

  void m_SetLinks () {

    queue < int > q;

    for (int i = 0; i < 26; ++ i) {
      if (tree[0].letter[i]) {
        q.push (tree[0].letter[i]);
      }
    }

    while (not q.empty ()) {

      int cur = q.front ();
      q.pop ();

      for (int i = 0; i < 26; ++ i) {

        if (not tree[cur].letter[i]) {
          continue;
        }

        int me = tree[cur].suffLink;
        while (me) {

          if (tree[me].letter[i]) {
            break;
          }

          me = tree[me].suffLink;
        }

        ++ lvl[tree[me].letter[i]];
        gr[tree[cur].letter[i]].push_back (tree[me].letter[i]);
        tree[tree[cur].letter[i]].suffLink = tree[me].letter[i];
        q.push (tree[cur].letter[i]);
      }
    }
  }
};
  
int main () {

  ios::sync_with_stdio (false);
  cin.tie (0);cout.tie (0);

  Aho aho;
  aho.Solve ();
}