【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;
}
【CF710F】String Set Queries(二进制分组,AC自动机)的更多相关文章
- CF710F String Set Queries
CF710F String Set Queries 支持字符串的插入和删除...SAM也干不了这个事 所以可以用cdq分治+AC自动机O(nlogn)解决 但是本题强制在线~~~ 我们还有一个工具,叫 ...
- Codeforces963C Frequency of String 【字符串】【AC自动机】
题目大意: 给一个串s和很多模式串,对每个模式串求s的一个最短的子串使得这个子串中包含至少k个该模式串. 题目分析: 均摊分析,有sqrt(n)种长度不同的模式串,所以有关的串只有msqrt(n)种. ...
- ZOJ3784 String of Infinity 高大上的AC自动机 数据原来这么水啊!不算输入输出只有5-7行
找给定s集合里面word全部是同一个字符的,这样的word有几个,如果数量<m就yes,否则就no.#include<iostream> #include<cstring> ...
- 模板汇总——AC自动机
AC自动机 模板题 HDU-2222 Keywords Search #include<bits/stdc++.h> using namespace std; #define LL lon ...
- AC自动机
AC自动机,全称Aho-Corasick自动机.如果没记错的话好像就是前缀自动机. 其实AC自动机就是KMP上树的产物.理解了KMP,那AC自动机应该也是很好理解的. 与KMP类似,AC自动机也是扔一 ...
- 【Codeforces710F】String Set Queries (强制在线)AC自动机 + 二进制分组
F. String Set Queries time limit per test:3 seconds memory limit per test:768 megabytes input:standa ...
- 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 ...
- CF710F-String Set Queries【AC自动机,二进制分组】
正题 题目链接:https://www.luogu.com.cn/problem/CF710F 题目大意 \(T\)次操作 往集合中加入一个字符串 往集合中删除一个字符串 给出一个模式串求出现的集合里 ...
- Codeforces 710F - String Set Queries(AC 自动机)
题面传送门 题意:强制在线的 AC 自动机. \(n,\sum|s|\leq 3\times 10^5\) 如果不是强制在线那此题就是道 sb 题,加了强制在线就不那么 sb 了. 这里介绍两种做法: ...
随机推荐
- WebGL——osg框架学习四
这篇我们接着来看一下DrawEntityActor类,我们来看看这个继承DrawActor的类到底做了什么事.我们之前学习了Drawable对应的DrawActor,那么我们类比的来看Drawable ...
- Netty源码分析第2章(NioEventLoop)---->第6节: 执行select操作
Netty源码分析第二章: NioEventLoop 第六节: 执行select操作 分析完了selector的创建和优化的过程, 这一小节分析select相关操作 跟到跟到select操作的入口 ...
- centos7.6 安装 openvpn--2.4.7
openvpn-server端 搭建 1,软件版本 Centos - 7.x easy-rsa - 3.0.3 OpenVPN - 2.4.7 2,安装 建议安装启用epel源,采用yum的方式安装o ...
- django orm 操作表
django orm 操作表 1.基本操作 增 models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs inser ...
- java之接口开发-初级篇
简述:转眼之间已经开发java有五年之余了,从以前的刚刚接触电脑,到现在的公司上班,真是转眼之间呀!前两年开发过前端,后台和Android,Android火的那几年,差点转去做Android,哈哈!后 ...
- 用 requests 模块从 Web 下载文件
用 requests 模块从 Web 下载文件 requests 模块让你很容易从 Web 下载文件,不必担心一些复杂的问题,诸如网络错误.连接问题和数据压缩.requests 模块不是 Python ...
- 配置idea
http://www.cnblogs.com/yangyquin/p/5285272.html
- wordpress登录密码框明文显示最后一个输入的字符
wordpress登录密码框明文显示最后一个输入的字符 (function(a){a.fn.dPassword=function(c){var e={interval:200,duration:100 ...
- java实验三实验报告
一.实验内容 1. XP基础 2. XP核心实践 3. 相关工具 二.实验过程(本次试验是在自己电脑上完成,没有使用实验楼) (一)敏捷开发与XP 1.XP是以开发符合客户需要的软件为目标而产生的一种 ...
- 冲刺One之站立会议7 /2015-5-20
2015-5-20 在登陆成功之后要实现的是聊天界面的交互过程,不同的IP进行信息和数据的传递,这方面我们上学期Java实验里面有过相关的内容,我们把它拿过来改了一下格式,试着看能不能成功,目前还没实 ...