CF710F cadena Set consultas [AC autómata + binario de paquetes]

agrupación binaria, de hecho, está por debajo de esas cosas, dibujar un punto áspero.

Fácil mostrar que cada uno se incorporó único \ (\ log \) veces, porque hay \ (\ log \) capa, por lo que podemos entender su complejidad abstracta es \ (n \ \ log \ n \) es.

Entonces hablar de la práctica de esta pregunta, nos encontramos con que cada vez que lo hace la complejidad de la fusión es controlable, es decir, se puede poner trie información también son reagrupadas y luego para cada punto autómata AC construido de nuevo, de manera que podamos hacer en línea.
En cuanto al número de cadenas de sub-consulta, sólo tenemos que consultar el árbol desde la raíz a fallar su número final muy bien.

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 53;
char s[maxn];
int ch[maxn][26], ed[maxn], fail[maxn], tr[maxn][26], siz[maxn];
int cnt = 1;

struct ACAM {
  int rt, sz;

  void ins(char* s) {
    int p = rt = ++cnt;
    sz = 1;
    while (*s) {
      int c = (*s++) - 'a';
      if (!ch[p][c]) ch[p][c] = ++cnt;
      p = ch[p][c];
    }
    ed[p] = 1;
  }

  void build() {
    queue<int> q;
    for (int i = 0; i < 26; i++)
      if (ch[rt][i]) {
        fail[tr[rt][i] = ch[rt][i]] = rt;
        q.push(tr[rt][i]);
      } else {
        tr[rt][i] = rt;
      }
    while (q.size()) {
      int u = q.front();
      q.pop();
      for (int i = 0; i < 26; i++) {
        if (ch[u][i]) {
          fail[tr[u][i] = ch[u][i]] = tr[fail[u]][i];
          q.push(tr[u][i]);
        } else {
          tr[u][i] = tr[fail[u]][i];
        }
      }
      siz[u] = ed[u] + siz[fail[u]];
    }
  }
};

int merge(int x, int y) {
  if (!x || !y) return x | y;
  ed[x] += ed[y];
  for (int i = 0; i < 26; i++) ch[x][i] = merge(ch[x][i], ch[y][i]);
  return x;
}

struct ACAutoMaton {
  ACAM rt[maxn];
  int top;

  ACAutoMaton() { top = 0; }

  void solve(char* s) {
    rt[++top].ins(s);
    while (top > 1 && rt[top].sz == rt[top - 1].sz) {
      rt[top - 1].rt = merge(rt[top - 1].rt, rt[top].rt);
      rt[top - 1].sz += rt[top].sz, top--;
    }
    rt[top].build();
  }

  int qry(char* s) {
    int ans = 0;
    for (int i = 1; i <= top; i++) {
      int p = rt[i].rt;
      for (char* t = s; *t;) p = tr[p][(*t++) - 'a'], ans += siz[p];
    }
    return ans;
  }
} INS, DEL;

signed main() {
  int _;
  scanf("%d", &_);
  while (_--) {
    int op;
    scanf("%d", &op), scanf("%s", s);
    if (op == 1) {
      INS.solve(s);
    }
    if (op == 2) {
      DEL.solve(s);
    }
    if (op == 3) {
      printf("%d\n", INS.qry(s) - DEL.qry(s));
      fflush(stdout);
    }
  }
  return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/Isaunoya/p/12540656.html
Recomendado
Clasificación