zoukankan      html  css  js  c++  java
  • 【CF710F】String Set Queries

    题面

    https://www.luogu.org/problem/CF710F

    题解

    删除的情况另开一个“可支持插入的$AC$自动机”,因为贡献可减。

    支持插入的$AC$自动机$=$$AC$自动机$+$二进制分组。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #define ri register int
    #define N 300300
    #define pb push_back
    
    using namespace std;
    struct node {
      int son[26],fail,v;
    } t[N];
    int st[N],top;
    int newnode() {
      return st[top--];
    }
    void insert(int u,string s){
      for (ri i=0,l=s.size();i<l;i++) {
        if (!t[u].son[s[i]-97]) t[u].son[s[i]-97]=newnode();
        u=t[u].son[s[i]-97];
      }
      t[u].v++;
    }
    
    void del(int rt){
      if (!rt) return;
      for (ri i=0;i<26;i++) del(t[rt].son[i]),t[rt].son[i]=0;
      t[rt].fail=t[rt].v=0; st[++top]=rt;
    }
    
    struct group {
      vector<string> p; int tot,rt;
      void insert(string s) {
        p.pb(s);
        ++tot;
      }
      void clear() {
        del(rt); 
        rt=newnode(); 
        p.clear(); 
        tot=0;
      }
      void build() {
        del(rt);
        rt=newnode();
        for (ri i=0;i<tot;++i) Insert(rt,p[i]);
        queue<int> q;
        t[rt].fail=rt;
        for (ri i=0;i<26;i++) if (t[rt].son[i]) q.push(t[rt].son[i]),t[t[rt].son[i]].fail=rt;
        while (!q.empty()) {
          int u=q.front(); q.pop();
          for (ri i=0;i<26;i++) if (t[u].son[i]) {
            int p=t[u].fail,v=t[u].son[i];
            while (p!=rt && !t[p].son[i]) p=t[p].fail;
            if (t[p].son[i]) t[v].fail=t[p].son[i]; else t[v].fail=rt;
            q.push(v);
            t[v].v+=t[t[v].fail].v;
          }
        }
      }
      
      int query(string s) {
        int ret=0,u=rt;
        for (ri i=0,l=s.size();i<l;i++) {
          int c=s[i]-97;
          if (t[u].son[c]) u=t[u].son[c];
          else {
            int p=t[u].fail;
            while (p!=rt && !t[p].son[c]) p=t[p].fail;
            if (t[p].son[c]) u=t[p].son[c];
            else u=rt;
          }
          ret+=t[u].v;
        }
        return ret;
      }
    } A[20],B[20];
    
    int tp1,tp2;
    void insert(string s){
      ++tp1; A[tp1].clear(); A[tp1].insert(s);
      while (tp1>1 && A[tp1].tot==A[tp1-1].tot) {
        for (ri i=0;i<A[tp1].tot;i++) A[tp1-1].insert(A[tp1].p[i]);
        A[tp1--].clear();
      }
      A[tp1].build();
    }
    void delete(string s){
      ++tp2; B[tp2].clear(); B[tp2].insert(s);
      while (tp2>1 && B[tp2].tot==B[tp2-1].tot) {
        for (ri i=0;i<B[tp2].tot;i++) B[tp2-1].insert(B[tp2].p[i]);
        B[tp2--].clear();
      }
      B[tp2].build();
    }
    int query(string s){
      int ret=0;
      for (ri i=1;i<=tp1;i++) ret+=A[i].query(s);
      for (ri i=1;i<=tp2;i++) ret-=B[i].query(s);
      return ret;
    }
    string s;
    int main(){
      ios::sync_with_stdio(false);
      for (ri i=1;i<N;i++) st[++top]=i;
      int m,opt;
      cin>>m;
      for (ri i=1;i<=m;i++) {
        cin>>opt>>s;
        if (opt==1) insert(s);
        if (opt==2) Delete(s);
        if (opt==3) cout<<query(s)<<endl;
      }
    }
  • 相关阅读:
    怎么能忘了N皇后(N Queens)?
    中序线索二叉树及相关算法概述(java实现)
    树遍历算法概述
    广义表与字符串
    KMP算法简述
    Linux常用系统符号总结
    linux 父、子shell变量传递问题
    数据结构总结之一栈与队列
    n!素因子p的幂 swjtuOJ 2090【数论】
    N!分解素因子及若干问题【转载】
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11279485.html
Copyright © 2011-2022 走看看