CF710F String Set Queries
CF710F String Set Queries
题意
动态支持加入删除字符串和字符串匹配
思路
动态 AC自动机
先不考虑动态情况。对于加入一个字符串,直接插入到自动机即可。
考虑删除。发现对于答案具有可减性,意思是对于同一个匹配串,答案可以表示为在自动机中匹配的答案减去删去的所有串匹配的答案。那我们考虑给所有删除的串也开一个 AC 自动机,每次询问在两个自动机中匹配将答案相减即可。
现在考虑动态情况。因为强制在线,且 AC 自动机是离线的,我们每插入一个字符串相当于重新建了一个自动机,每次在所有自动机中匹配结果的和即为答案。减少时间消耗的唯一途径是对 AC 自动机进行合并。
考虑如何合并时间复杂度有保证且优秀。有很多办法,比如根号重构、二进制分组等。后者比较优秀也比较好写。
实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
#include<string>
using namespace std;
namespace star
{
const int maxn=3e5+10;
struct ACmation{
int tot,son[maxn][26],val[maxn],fail[maxn],st[maxn],N,n,siz[maxn],beg[maxn];
string S[maxn];
inline void ins(string s,int ro){
int x=ro;
for(auto t:s){
t-='a';
if(son[x][t]==ro){
son[x][t]=++tot;
for(int j=0;j<26;j++) son[tot][j]=ro;
}
x=son[x][t];
}
val[x]++;
}
inline void build(int ro){
fail[ro]=ro;
static int q[maxn];
int hd=0,tl=1;
q[tl]=ro;
while(hd<tl){
int x=q[++hd];
for(int t=0;t<26;t++){
int u=son[x][t];
if(u!=ro){
fail[u]=x==ro?x:son[fail[x]][t];
if(son[fail[x]][t]!=u) val[u]+=val[son[fail[x]][t]];
q[++tl]=u;
}else son[x][t]=son[fail[x]][t];
}
}
}
inline int query(string s,int x){
int ans=0;
for(auto t:s)
x=son[x][t-'a'],ans+=val[x];
return ans;
}
inline void merge(){
siz[--N]<<=1;
for(int i=st[N];i<=tot;i++){
val[i]=fail[i]=0;
for(int j=0;j<26;j++) son[i][j]=0;
}
tot=st[N];
for(int i=0;i<26;i++) son[tot][i]=tot;
for(int i=beg[N];i<=n;i++) ins(S[i],st[N]);
build(st[N]);
}
inline void insert(string s){
st[++N]=++tot;
for(int i=0;i<26;i++) son[tot][i]=tot;
siz[N]=1;
ins(s,tot),build(st[N]);
S[beg[N]=++n]=s;
while(siz[N]==siz[N-1]) merge();
}
inline int query(string s){
int ans=0;
for(int i=1;i<=N;i++) ans+=query(s,st[i]);
return ans;
}
}a,b;
inline void work(){
int m;cin>>m;
while(m--){
int op;string s;
cin>>op>>s;
switch(op){
case 1:a.insert(s);break;
case 2:b.insert(s);break;
case 3:cout<<a.query(s)-b.query(s)<<endl;break;
}
}
}
}
signed main(){
star::work();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现