CF710F-String Set Queries【AC自动机,二进制分组】
正题
题目链接:https://www.luogu.com.cn/problem/CF710F
题目大意
\(T\)次操作
- 往集合中加入一个字符串
- 往集合中删除一个字符串
- 给出一个模式串求出现的集合里面的字符串个数
解题思路
删除的话改成加入一个权值为\(-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自动机,二进制分组】的更多相关文章
- 【Codeforces710F】String Set Queries (强制在线)AC自动机 + 二进制分组
F. String Set Queries time limit per test:3 seconds memory limit per test:768 megabytes input:standa ...
- GRE Words Revenge AC自动机 二进制分组
GRE Words Revenge 题意和思路都和上一篇差不多. 有一个区别就是需要移动字符串.关于这个字符串,可以用3次reverse来转换, 前面部分翻转一下, 后面部分翻转一下, 最后整个串翻转 ...
- CF710F String Set Queries
CF710F String Set Queries 支持字符串的插入和删除...SAM也干不了这个事 所以可以用cdq分治+AC自动机O(nlogn)解决 但是本题强制在线~~~ 我们还有一个工具,叫 ...
- Searching the String ZOJ - 3228 AC自动机查询升级版
题意:先给你一个不超过1000000长度的大串s:接下来输入一个n代表接下来输入的小串个数,小串长度不超过6. 小串分两种类型0和1类型. 0类型表示小串在大串中的最大匹配个数就是常规的AC自动机的做 ...
- ZOJ3784 String of Infinity(AC自动机&&强连通分量)
题意:给你n个禁止串,然后你只能用字符表的前m个字符去写一个无限长的串,要求是不能包含禁止串,而且串在后面不能出现循环 比赛的时候想的是先建一个自动机,然后将自动机确定化,不能到达的状态全部弄出来.但 ...
- LA 4670 Dominating Patterns (AC自动机)
题意:给定n个字符串和一个文本串,查找哪个字符串出现的次数的最多. 析:一匹配多,很明显是AC自动机.只需要对原来的进行修改一下,就可以得到这个题的答案, 计算过程中,要更新次数,并且要映射字符串.如 ...
- 【CF710F】String Set Queries(二进制分组,AC自动机)
[CF710F]String Set Queries(二进制分组,AC自动机) 题面 洛谷 CF 翻译: 你有一个字符集合\(D\),初始为空, 有三种操作: 往\(D\)中加入一个串:从\(D\)中 ...
- 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 ...
- Codeforces 710F - String Set Queries(AC 自动机)
题面传送门 题意:强制在线的 AC 自动机. \(n,\sum|s|\leq 3\times 10^5\) 如果不是强制在线那此题就是道 sb 题,加了强制在线就不那么 sb 了. 这里介绍两种做法: ...
随机推荐
- maven打包war,导入本地jar包
方法1: 一 . 在项目根目录创建lib文件夹,把jar放入lib文件夹中 二 . 在项目中使用本地jar pom文件配置如下: <properties> <project.buil ...
- 教你IO流来便利电脑磁盘所有文件,把图片放到一个文件夹里(会发现什么不可告人的密码)
一.需求 我要把C盘下面的所有图片都拿出来,放到一个新文件夹中.今天小编一身正气,看看有没有什么意外发现!!学会看看自己的盘,悄悄的哦!!! 二.代码展示(运行时间可能有点长) import java ...
- 定时执行的任务Quartz.net
- WPF---数据绑定之PasswordBox绑定(八)
一.概述 众所周知,绑定的源既可以是依赖属性也可以是普通的CLR属性,而绑定的目标只能是依赖属性. 控件PasswordBox的Password属性不是依赖属性,不可以作为绑定的目标与后台数据进行绑定 ...
- C# 委托讲解
首先,委托的使用场景:A的某些功能,只有在B需要触发时触发,委托就是用来做中间通讯的渠道. 假设:现在有个大佬A,A有个小弟B,B在受到羞辱时就会通过电话Delegate通知A自己被羞辱了,A在这时就 ...
- Java String 综述(上篇)
摘要: Java 中的 String类 是我们日常开发中使用最为频繁的一个类,但要想真正掌握的这个类却不是一件容易的事情.笔者为了还原String类的真实全貌,先分为上.下两篇博文来综述Java中的S ...
- 多线程编程<四>
1 /** 2 * 守护线程daemon['diːmən] 3 * @author Administrator 4 * 5 */ 6 public class DaemonDemo { 7 publi ...
- opencv入门系列教学(六)图像上的算术运算(加法、融合、按位运算)
0.序言 这一篇博客我们将学习图像的几种算术运算,例如加法,减法,按位运算等. 1.图像加法 我们可以通过OpenCV函数 cv.add() 或仅通过numpy操作 res=img1+img2 res ...
- RapidSVN设置diff和edit工具
菜单栏 -> View -> Preferences -> Programs选择相应的配置页即可 需要配置的路径,默认都在 /usr/bin目录下的 editor可以用ged ...
- vue JS获取当前时间并格式化 ( 前端小细节,大进步 )
JS // 获取并且格式化时间 formatter (thistime, fmt) { let $this = new Date(thistime) let o = { ...