正题

题目链接:https://www.luogu.com.cn/problem/CF710F


题目大意

\(T\)次操作

  1. 往集合中加入一个字符串
  2. 往集合中删除一个字符串
  3. 给出一个模式串求出现的集合里面的字符串个数

解题思路

删除的话改成加入一个权值为\(-1\)的字符串就是全都是加入操作了。

然后就可以像[SDOI2014]向量集一样的做法了,维护一个线段树,然后第\(i\)次加入修改第\(i\)个节点,然后回朔的时候,如果一个区间\([l,r]\)加入了\(r-l+1\)个字符串(加满了)的话就直接把下面的\(AC\)自动机合并(或者直接把\(l\sim r\)重新暴力加入到一个\(AC\)自动机),然后匹配的时候把目前合并了的顶层\(AC\)自动机分别求和就好了。

时间复杂度\(O(n\log n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define ll long long
using namespace std;
const int N=3e5+10;
int T,n,cnt,val[N],rt[N<<2],siz[N<<2],last[N<<2];
vector<int> v[N];
char s[N];
struct ACM{
int ch[N<<3][26],fail[N<<3],cnt;
ll w[N<<3];queue<int> q;
void Insert(int &now,vector<int>&s,int val){
if(!now)now=++cnt;int x=now;
for(int i=0;i<s.size();i++){
int c=s[i];
if(!ch[x][c])ch[x][c]=++cnt;
x=ch[x][c];
}
w[x]+=val;
return;
}
void GetFail(int rt){
for(int i=0;i<26;i++)
if(ch[rt][i])q.push(ch[rt][i]);
else ch[rt][i]=rt;
while(!q.empty()){
int x=q.front();q.pop();
if(!fail[x])fail[x]=rt;
w[x]+=w[fail[x]];
for(int i=0;i<26;i++){
if(!ch[x][i])ch[x][i]=ch[fail[x]][i];
else{
fail[ch[x][i]]=ch[fail[x]][i];
q.push(ch[x][i]);
}
}
}
return;
}
ll Find(int x,int n,char *s){
ll ans=0;
for(int i=0;i<n;i++){
x=ch[x][s[i]-'a'];
ans+=w[x];
}
return ans;
}
void Clear(int d){
while(cnt>d){
memset(ch[cnt],0,sizeof(ch[cnt]));
fail[cnt]=w[cnt]=0;cnt--;
}
return;
}
}A;
void Change(int x,int L,int R,int pos){
if(!siz[x])last[x]=A.cnt;
if(L==R){siz[x]++;A.Insert(rt[x],v[L],val[L]);A.GetFail(rt[x]);return;}
int mid=(L+R)>>1;
if(pos<=mid)Change(x*2,L,mid,pos);
else Change(x*2+1,mid+1,R,pos);
siz[x]=siz[x*2]+siz[x*2+1];
if(siz[x]==R-L+1){
A.Clear(last[x]);
for(int i=L;i<=R;i++)
A.Insert(rt[x],v[i],val[i]);
A.GetFail(rt[x]);
}
return;
}
ll Ask(int x,int L,int R,int l,int r){
if(L==l&&R==r&&siz[x]==R-L+1)return A.Find(rt[x],n,s);
int mid=(L+R)>>1;
if(r<=mid)return Ask(x*2,L,mid,l,r);
if(l>mid)return Ask(x*2+1,mid+1,R,l,r);
return Ask(x*2,L,mid,l,mid)+Ask(x*2+1,mid+1,R,mid+1,r);
}
int main()
{
scanf("%d",&T);
for(int p=1;p<=T;p++){
int op;
scanf("%d%s",&op,s);
// op=p%3+1;s[0]='a';
n=strlen(s);
if(op<=2){
v[++cnt].resize(n);val[cnt]=(op==1)?1:-1;
for(int i=0;i<n;i++)v[cnt][i]=s[i]-'a';
Change(1,1,T,cnt);
}
else{
if(!cnt){puts("0");fflush(stdout);continue;}
printf("%lld\n",Ask(1,1,T,1,cnt));
fflush(stdout);
}
}
return 0;
}

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

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

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

  2. GRE Words Revenge AC自动机 二进制分组

    GRE Words Revenge 题意和思路都和上一篇差不多. 有一个区别就是需要移动字符串.关于这个字符串,可以用3次reverse来转换, 前面部分翻转一下, 后面部分翻转一下, 最后整个串翻转 ...

  3. CF710F String Set Queries

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

  4. Searching the String ZOJ - 3228 AC自动机查询升级版

    题意:先给你一个不超过1000000长度的大串s:接下来输入一个n代表接下来输入的小串个数,小串长度不超过6. 小串分两种类型0和1类型. 0类型表示小串在大串中的最大匹配个数就是常规的AC自动机的做 ...

  5. ZOJ3784 String of Infinity(AC自动机&&强连通分量)

    题意:给你n个禁止串,然后你只能用字符表的前m个字符去写一个无限长的串,要求是不能包含禁止串,而且串在后面不能出现循环 比赛的时候想的是先建一个自动机,然后将自动机确定化,不能到达的状态全部弄出来.但 ...

  6. LA 4670 Dominating Patterns (AC自动机)

    题意:给定n个字符串和一个文本串,查找哪个字符串出现的次数的最多. 析:一匹配多,很明显是AC自动机.只需要对原来的进行修改一下,就可以得到这个题的答案, 计算过程中,要更新次数,并且要映射字符串.如 ...

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

    [CF710F]String Set Queries(二进制分组,AC自动机) 题面 洛谷 CF 翻译: 你有一个字符集合\(D\),初始为空, 有三种操作: 往\(D\)中加入一个串:从\(D\)中 ...

  8. 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 ...

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

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

随机推荐

  1. dubbo-admin管理控制台安装

    拉项目切换分支到master git clone https://github.com/apache/dubbo-admin.git /var/tmp/dubbo-admin 打开项目修改配置 dub ...

  2. js随机显示图片

    定义一个图片数组,生成一个随机数对应数据索引. window.onload = choosePic; function choosePic() { var myPix = new Array(&quo ...

  3. nginx 实现反向代理、负载均衡、高可用

    转自:https://blog.csdn.net/zy1471162851/article/details/91795712 tip:   nginx是一款高性能的http 服务器/反向代理服务器及电 ...

  4. hystrix熔断机制修改配置

    0.注意 0.1.如果使用command 的 execute( )方法的话,其实在一个for循环,执行多次,其实每个的执行顺序并不是固定的,如果你想固定,需要使用queue circuit break ...

  5. 快速排序(C++)

    快速排序 快速排序是面试中经常问到的排序算法 基本思想:通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小, 则可分别对这两部分记录继续进行排序,以达到整个序 ...

  6. RabbitMQ-进阶

    目录 过期时间TTL 设置队列TTL 消息确认机制的配置 死信队列 内存磁盘的监控 RabbitMQ的内存控制 命令的方式 配置文件方式 rabbitmq.conf RabbitMQ的内存换页 Rab ...

  7. Mybatis-Plus - 条件构造器 QueryWrapper 的使用

    目录 前言 查询示例 基础代码 QueryWrapper 的基本使用 QueryWrapper 的lambada写法 LambadaQueryWrapper 的使用 LambdaQueryChainW ...

  8. 聊聊 Jmeter 如何并发执行 Python 脚本

    1. 前言 大家好,我是安果! 最近有小伙伴后台给我留言,说自己用 Django 写了一个大文件上传的 Api 接口,现在想本地检验一下接口并发的稳定性,问我有没有好的方案 本篇文章以文件上传为例,聊 ...

  9. Sentry Web 性能监控 - Web Vitals

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  10. Pytest系列(15)- 多重校验插件之pytest-assume的详细使用

    如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 前言 pytest中可以用pyth ...