【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;
}

【CF710F】String Set Queries(二进制分组,AC自动机)的更多相关文章

  1. CF710F String Set Queries

    CF710F String Set Queries 支持字符串的插入和删除...SAM也干不了这个事 所以可以用cdq分治+AC自动机O(nlogn)解决 但是本题强制在线~~~ 我们还有一个工具,叫 ...

  2. Codeforces963C Frequency of String 【字符串】【AC自动机】

    题目大意: 给一个串s和很多模式串,对每个模式串求s的一个最短的子串使得这个子串中包含至少k个该模式串. 题目分析: 均摊分析,有sqrt(n)种长度不同的模式串,所以有关的串只有msqrt(n)种. ...

  3. ZOJ3784 String of Infinity 高大上的AC自动机 数据原来这么水啊!不算输入输出只有5-7行

    找给定s集合里面word全部是同一个字符的,这样的word有几个,如果数量<m就yes,否则就no.#include<iostream> #include<cstring> ...

  4. 模板汇总——AC自动机

    AC自动机 模板题 HDU-2222 Keywords Search #include<bits/stdc++.h> using namespace std; #define LL lon ...

  5. AC自动机

    AC自动机,全称Aho-Corasick自动机.如果没记错的话好像就是前缀自动机. 其实AC自动机就是KMP上树的产物.理解了KMP,那AC自动机应该也是很好理解的. 与KMP类似,AC自动机也是扔一 ...

  6. 【Codeforces710F】String Set Queries (强制在线)AC自动机 + 二进制分组

    F. String Set Queries time limit per test:3 seconds memory limit per test:768 megabytes input:standa ...

  7. CodeForces - 710F:String Set Queries (二进制分组 处理 在线AC自动机)

    ou should process m queries over a set D of strings. Each query is one of three kinds: Add a string ...

  8. CF710F-String Set Queries【AC自动机,二进制分组】

    正题 题目链接:https://www.luogu.com.cn/problem/CF710F 题目大意 \(T\)次操作 往集合中加入一个字符串 往集合中删除一个字符串 给出一个模式串求出现的集合里 ...

  9. Codeforces 710F - String Set Queries(AC 自动机)

    题面传送门 题意:强制在线的 AC 自动机. \(n,\sum|s|\leq 3\times 10^5\) 如果不是强制在线那此题就是道 sb 题,加了强制在线就不那么 sb 了. 这里介绍两种做法: ...

随机推荐

  1. svn树冲突的解决方法

    树冲突 就是开发人员移动.重命名.删除一个文件或文件夹,而另一名开发人员也对它们进行了移动.重命名.删除或者仅仅是修改时就会发生树冲突.有很多种不同的情形可以导致树冲突,而且不同的情形需要不同的步骤来 ...

  2. 【SIKIA计划】_06_Unity2D游戏开发-拾荒者笔记

    [新增分类]Animations 动画——Animation——AnimatorControllerPrefabs 预制 [素材导入]unitypackage 素材包Sprites Editor 编辑 ...

  3. 【坚持】Selenium+Python学习记录 DAY10

    2018/05/31-2018/06/1 [官方文档](https://www.jetbrains.com/help/pycharm/set-up-a-git-repository.html) 通过p ...

  4. python实现简单线性回归

    之前推导了一元线性回归和多元线性回归,今天就用python来实现一下一元线性回归 先看下之前推导的结果   ,  第一种是用循环迭代的计算方法.这里的x,y是numpy中的array类型 def su ...

  5. PHP 伪协议

    1.file:// file://用于访问本地文件系统,不受allow_url_fopen影响 <?php include($_GET['file']); ?> 2.http:// GET ...

  6. 团队博客作业Week4 --- 学霸网站--NABC

    1.需求(Need) 伴随着经济的发展,科学技术取得了飞速的发展,互联网在各行各业的发展中取得了广泛的应用.随着这些事物的发展,我们每个人都会接触到相当庞大的数据.如何在这些数据中找到自己需要的,如何 ...

  7. 转载 intellij IDEA 使用体验 (本人感觉它的使用是一种趋势)

    从去年开始转java以来,一直在寻找一款趁手的兵器,eclipse虽然是很多java程序员的首选,但是我发现一旦安装了一些插件,workspace中的项目达到数10个以后,经常崩溃,实在影响编程的心情 ...

  8. Task 4.2 求一个矩阵的最大子矩阵的和

    任务:输入一个二维整形数组,数组里有正数也有负数.二维数组中连续的一个子矩阵组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.要求时间复杂度为O(n). (1)设计思想:把二维矩阵分解成 ...

  9. mvc 路由配置-学习

    MapRoute(RouteCollection, String, String) 映射指定的URL路由. 'Declaration <ExtensionAttribute> _ Publ ...

  10. Internet History, Technology and Security (Week5.1)

    Week5 The Transport layer is built on the Internetwork layer and is what makes our network connectio ...