• CF710F String Set Queries


    CF710F String Set Queries 

    支持字符串的插入和删除。。。SAM也干不了这个事

    所以可以用cdq分治+AC自动机O(nlogn)解决

    但是本题强制在线~~~

    我们还有一个工具,叫做二进制分组!

    所以,每组建立一个AC自动机,合并的时候,AC自动机合并。最后再build失配指针

    随机删除?虽然不是栈序删除了,但是,统计数量具有贡献独立性,再对删除串建立一个AC自动机集群即可!

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=3e5+5;
    int m;
    int ch[N][26];
    int vis[N][26];
    int fail[N],num[N],tot[N];
    int rt[N],sz[N];    
    int cnt,totid;
    struct AC{
        int sta[N],top;
        int merge(int x,int y){
        //    cout<<"merge "<<x<<" "<<y<<endl;
            if(!x||!y) return x+y;
            for(reg i=0;i<26;++i) ch[x][i]=merge(ch[x][i],ch[y][i]);
            num[x]+=num[y];
            return x;
        }
        void build(int id){
            queue<int>q;
            for(reg i=0;i<26;++i){
                if(ch[rt[id]][i]) fail[vis[rt[id]][i]=ch[rt[id]][i]]=rt[id],q.push(vis[rt[id]][i]);
                else vis[rt[id]][i]=rt[id];
            }
            while(!q.empty()){
                int x=q.front();q.pop();
                tot[x]=num[x]+tot[fail[x]];
                for(reg i=0;i<26;++i){
                    if(ch[x][i]){
                        fail[vis[x][i]=ch[x][i]]=vis[fail[x]][i];
                        q.push(vis[x][i]);
                    }else{
                        vis[x][i]=vis[fail[x]][i];
                    }
                }
            }
        }
        int query(char *s){
            int len=strlen(s+1);
            int ret=0;
            for(reg i=1;i<=top;++i){
                int id=sta[i];
                int now=rt[id];
                for(reg i=1;i<=len;++i){
                    now=vis[now][s[i]-'a'];
                    ret+=tot[now];
                }
            }
            return ret;
        }
        void ins(char *s){
            int id=++totid;
            int len=strlen(s+1);
            if(!rt[id]) rt[id]=++cnt;
            int now=rt[id];
            for(reg i=1;i<=len;++i){
                int x=s[i]-'a';
                ch[now][x]=++cnt;
                now=ch[now][x];
            }
            ++num[now];
            //dfs(rt[id]);
        //    cout<<rt[id]<<" "<<cnt<<endl;
            sz[id]=1;
        //    cout<<" after ins "<<id<<endl;
            while(top&&sz[sta[top]]==sz[id]) rt[id]=merge(rt[id],rt[sta[top]]),sz[id]+=sz[sta[top]],--top;
        //    cout<<" after merge "<<endl;
            build(id);
            sta[++top]=id;
            
        }
    }f,d;
    char s[N];
    int main(){
        rd(m);
        int op;
        for(reg i=1;i<=m;++i){
            rd(op);scanf("%s",s+1);
            if(op==1)f.ins(s);
            else if(op==2)d.ins(s);
            else {
                printf("%d
    ",f.query(s)-d.query(s));
            }
            fflush(stdout);
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/2/24 15:19:38
    */

    二进制分组,对于许多插入删除根本不虚,反正暴力重构删除,O(nlogn)

    (当然如果贡献不独立,还是cdq或者线段树分治吧,,)

  • 相关阅读:
    python各种类型转换-int,str,char,float,ord,hex,oct等
    pandas快速入门
    python里面,将多个list列表合并成一个list列表
    对字符串进行切分的技巧
    Ubuntu 16.04 安装navicat (tar.gz)
    ubuntu 16.04 如何升级系统的scrapy旧版本(1.0.3)到最新版本
    ubuntu下,敲命令scrapy出现:0: UserWarning: You do not have a working installation of the service_identity module: 'cannot import name 'opentype''. Please install it from <https://pypi.python.org/pypi/servic
    Ubuntu下解压缩zip,tar,tar.gz,tar.bz2格式的文件
    简单的查看进程信息
    python正则表达式
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10426608.html
Copyright © 2020-2023  润新知