• 【CF710F】String Set Queries(二进制分组,AC自动机)


    【CF710F】String Set Queries(二进制分组,AC自动机)

    题面

    洛谷
    CF
    翻译:
    你有一个字符集合(D),初始为空,
    有三种操作:
    (D)中加入一个串;从(D)中删除一个串;给定一个串(S),询问(D)中的串在(S)中总共出现了多少次。

    题解

    询问显然就是将(S)放在所有(D)构成的(AC)自动机上跑。
    所以我们需要一种方法,可以动态的支持(AC)自动机的插入以及删除。
    先考虑删除,这个很好办,我们可以维护两个(AC)自动机,一个记录插入,一个记录删除,将串在两个上面分别跑再做差就好了。这样子删除也变成了插入。
    那么如何插入?
    我们对于串二进制分组,因为串和串之间是独立的,所以可以对于每一组的串建立一个(AC)自动机,合并块的时候直接重构(AC)自动机就好了。
    写起来很爽啊。我又回到了C++STL选手???string真好用

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAX 300300
    #define pb push_back
    struct Node{int son[26],fail,v;}t[MAX];
    int St[MAX],top;
    int NewNode(){return St[top--];}
    void Insert(int u,string s)
    {
        for(int i=0,l=s.length();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+=1;
    }
    void Del(int rt)
    {
        if(!rt)return;
        for(int 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(int i=0;i<tot;++i)Insert(rt,p[i]);
                queue<int> Q;t[rt].fail=rt;
                for(int 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(int 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(int i=0,l=s.length();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(int 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(int 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(int i=1;i<=tp1;++i)ret+=A[i].Query(s);
        for(int i=1;i<=tp2;++i)ret-=B[i].Query(s);
        return ret;
    }
    int m,opt;
    string s;
    int main()
    {
        ios::sync_with_stdio(false);
        for(int i=1;i<MAX;++i)St[++top]=i;
        cin>>m;
        while(m--)
        {
            cin>>opt>>s;
            if(opt==1)Insert(s);
            if(opt==2)Delete(s);
            if(opt==3)cout<<Query(s)<<endl;
        }
        return 0;
    }
    
    
  • 相关阅读:
    「应用管理与交付」为什么会成为云原生新的价值聚焦点?
    Quick BI:降低使用门槛,大东鞋业8000家门店的数据导航
    如何用Netty写一个高性能的分布式服务框架?
    印度批准苹果和三星1430亿美元的智能手机制造计划
    东京证券交易所暂停了全天交易,与黑客有关吗?
    这些杀毒软件现漏洞,可能使计算机更易受黑客攻击
    又躺赚1亿?东方联盟创始人郭盛华,会的仅仅是技术吗?
    谷歌的VR虚拟现实为何失败了?VR的未来何去何从?
    爆料电脑天才郭盛华的稀有童年照,原来小时候就很帅
    好莱坞野心导演:郭盛华的传奇故事将拍黑客电影?他会参演吗?
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9468874.html
Copyright © 2020-2023  润新知