codeforce710f

題目大意:m次操作,3種操作,添加一個新串,刪除一個串,給一個串詢問集合裏所有串的出現次數之和。要求強制在線。

      維護兩個集合,一個維護增加串,一個用來維護刪除串,結果即爲這兩個集合裏字符串的出現次數之差。由於題目要求強制在線,每次刪減後都要重建AC自動機,但這樣顯然會T掉。所以需要在線的ac自動機。。。

     二進制分組。。。。。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<string.h>
using namespace std;
char s[300010];
queue<int>q;
struct Q{
    int sum[300010],num[300010],T[300010][30],S[300010][30],fa[300010],A[30],root[30],cnt=0;
    void insert(int x,int &f){
        if(f==0) f=++cnt;
        if(s[x]==0){
            sum[f]++;
            return;
        }
        int v=s[x]-'a';
        insert(x+1,T[f][v]);
    }
    void build(int x){
        int i,u,v;
        fa[x]=x;
        for(i=0;i<27;i++){
            int v=T[x][i];
            if(v){
                S[x][i]=v;
                fa[v]=x;
                q.push(v);
            }
            else S[x][i]=x;
        }
        for(;q.size();q.pop()){
            u=q.front();
            num[u]=num[fa[u]]+sum[u];
            for(i=0;i<27;i++){
                v=T[u][i];
                if(v){
                    fa[v]=S[fa[u]][i];
                    S[u][i]=v;
                    q.push(v);
                }
                else S[u][i]=S[fa[u]][i];
            }
        }
    }
    int merge(int a,int b){
        if(a==0||b==0) return a+b;
        sum[a]+=sum[b];
        int i;
        for(i=0;i<27;i++) T[a][i]=merge(T[a][i],T[b][i]);
        return a;
    }
    void add(){
        insert(0,root[0]);
        int i;
        for(i=0;i<=20;i++){
            if(A[i]){
               root[i+1]=merge(root[i+1],root[i]);
               root[i]=A[i]=0;
            }
            else break;
        }
        A[i]=1;
        build(root[i]);
    }
    long long qsum(){
        int i,p,j;
        long long ans=0;
        for(i=0;i<=20;i++){
           p=root[i];
           for(j=0;s[j];j++){
               p=S[p][s[j]-'a'];
               ans+=num[p];
           }
        }
        return ans;
    }
}A,B;
int main(){
    int i,n,a;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%d%s",&a,s);
        if(a==1) A.add();
        else if(a==2) B.add();
        else{
            printf("%lld\n",A.qsum()-B.qsum());
            fflush(stdout);
        }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章