【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 了. 这里介绍两种做法: ...
随机推荐
- HTML6的10个高级新特性
网络技术正趋向于发展为一个巨大的移动APP市场,在Web开发的革命浪潮中起着指示性作用,自HTML引入以来,应用程序变得So easy,web开发中运用先进技术也很容易处理各种复杂Bug. 作为专业的 ...
- [codeForce-1006C]-Three Parts of the Array (简单题)
You are given an array d1,d2,…,dnd1,d2,…,dn consisting of nn integer numbers. Your task is to split ...
- valgrind使用简介
1.问题 虽然C/C++是一种非常有用且功能强大的语言,但很难调试. 某些时候可能遇到内存错误. 如果知道出错 ,或者程序一直崩溃,我们可以用gdb/DBX去调试. 但是,有时遇到的问题是由于内存错误 ...
- HTML文件转Word文件格式
这是我需要转换的HTML文件 第一步~ 使用我们的福昕阅读器将我们.html文件打开,如下图 第二步: 点击“文件”——“另存为”——选择一个你自己喜欢的位置存放文件,此时的文件已经被转换成了.pdf ...
- 在Maven上Web项目添加Spring框架
1. pom.xml添加Spring依赖包 <!-- spring 核心依赖--> <!-- context依赖beans,aop,core,expression;core依赖log ...
- 高可用OpenStack(Queen版)集群-13.分布式存储Ceph
参考文档: Install-guide:https://docs.openstack.org/install-guide/ OpenStack High Availability Guide:http ...
- ceilometer 源码分析(polling)(O版)
一.简单介绍ceilometer 这里长话短说, ceilometer是用来采集openstack下面各种资源的在某一时刻的资源值,比如云硬盘的大小等.下面是官网现在的架构图 这里除了ceilomet ...
- Java之JSP和Servlet基础知识
JSP基础 JSP起源 JSP,JavaServer Pager的简称.由SUN倡导并联合其它公司创建. JSP是一门脚本语言 JSP可以嵌入到HTML中 JSP拥有Java语言的所有特性 面向对象. ...
- 第十三次作业psp
psp 进度条 代码累积折线图 博文累积折线图 psp饼状图
- 结对编程-->总结报告
项目github地址 PSP时间表格 结对编程中关于Information Hiding, Interface Design, Loose Coupling原则的使用 Information Hidi ...