Cod sursa(job #2231744)

Utilizator Stefan_RaduStefan Radu Stefan_Radu Data 15 august 2018 19:52:11
Problema Aho-Corasick Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 3.04 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;
    cin >> n;
    ans.resize (n + 1);

    root = new Node ();
    root -> suffLink = root;

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

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

    m_SetLinks ();
  }

  void Solve () {

    Node* curNode = root;
    for (auto x : s) {

      if (not curNode -> nextNode[L (x)]) {

        while (curNode != root) {

          if (curNode -> nextNode[L (x)]) {
            break;
          }

          curNode = curNode -> suffLink;
        }
      }

      if (curNode -> nextNode[L (x)]) {
        curNode = curNode -> nextNode[L (x)];
      }

      ++ curNode -> frecv;
      /* cerr << "lol\n"; */
    }

    /* cerr << "alle"; */
    m_Complete (root);

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

private:

  struct Node {

    Node () {

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

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

    int frecv, wordIndex;
    Node *nextNode[26], *suffLink;
    vector < Node* > inv;
  };

  int n;
  string s;
  Node *root;
  vector < int > ans;
   
  void m_Insert (string &s, int wordIndex) {

    Node *curNode = root;

    for (auto x : s) {

      if (not curNode -> nextNode[L (x)]) {
        curNode -> nextNode[L (x)] = new Node ();
      }

      curNode = curNode -> nextNode[L (x)];
    }

    curNode -> wordIndex = wordIndex;
  }

  void m_SetLinks () {

    queue < Node* > q;

    for (int i = 0; i < 26; ++ i) {
      if (root -> nextNode[i]) {
        q.push (root -> nextNode[i]);
        root -> nextNode[i] -> suffLink = root;
        root -> inv.push_back (root -> nextNode[i]);
      }
    }

    while (not q.empty ()) {

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

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

        if (not curNode -> nextNode[i]) {
          continue;
        }

        auto me = curNode -> suffLink;

        while (me != root) {

          if (me -> nextNode[i]) {
            break;
          }

          me = me -> suffLink;
        }

        if (me -> nextNode[i]) {
          curNode -> nextNode[i] -> suffLink = me -> nextNode[i];
          me -> nextNode[i] -> inv.push_back (curNode -> nextNode[i]);
        }
        else {
          curNode -> nextNode[i] -> suffLink = root;
          root -> inv.push_back (curNode -> nextNode[i]);
        }

        q.push (curNode -> nextNode[i]);
      }
    }
  }

  void m_Complete (Node *curNode) {

    for (auto x : curNode -> inv) {
      m_Complete (x);
      curNode -> frecv += x -> frecv;
    }

    ans[curNode -> wordIndex] = curNode -> frecv;
  }
};
  
int main () {

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

  /* freopen ("ahocorasick.in", "r", stdin); */
  /* freopen ("ahocorasick.out", "w", stdout); */

  Aho aho;
  aho.Solve ();
}