CF163E e-Government(AC自动机+树状数组维护fail树的DFS序)
时间:2021-07-13
本文章向大家介绍CF163E e-Government(AC自动机+树状数组维护fail树的DFS序),主要包括CF163E e-Government(AC自动机+树状数组维护fail树的DFS序)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
给出n个字符串,每个字符串有两种状态:退役和服役
三种操作:
1)询问当前服役的字符串在询问字符串内的出现次数之和。
2)把一个退役的字符串设为服役。
3)把一个服役的字符串设为退役。
如何处理操作1?
对所有字符串建出AC自动机,建出fail树,求子树和。
每个模式串s_i在t中出现的次数之和就是fail树上根到当前节点的路径的点权之和。
操作2 3的修改操作,就是把某个点权+1或-1。
所以可以用线段树维护 每个节点到根节点的路径点权之和。
单点修改影响的是整个子树。
这里涉及到对fail树的dfs序的区间修改和区间询问,但是有一个巨巨巨恶心的点,就是卡线段树,上线段树一定会MLE。
网上找了个树状数组维护区间修改的板子...
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+500;
int n,q,tr[maxn][26],fail[maxn],tot;
vector<int> g[maxn];
long long cnt[maxn];
string t,s;
int ed[maxn];
int dfn[maxn],id[maxn],tol,sz[maxn];
int insert (string s) {
int u=0;
for (char i:s) {
if (!tr[u][i-'a']) tr[u][i-'a']=++tot;
u=tr[u][i-'a'];
}
cnt[u]++;
return u;
}
void build () {
queue<int> q;
for (int i=0;i<26;i++) {
if (tr[0][i]) {
q.push(tr[0][i]);
}
}
while (q.size()) {
int u=q.front();
q.pop();
for (int i=0;i<26;i++) {
if (tr[u][i]) {
fail[tr[u][i]]=tr[fail[u]][i];
q.push(tr[u][i]);
}
else {
tr[u][i]=tr[fail[u]][i];
}
}
}
}
long long c[maxn<<2],lz[maxn<<2];
void Build (int i,int l,int r) {
if (l==r) {
c[i]=cnt[id[l]];
return;
}
int mid=(l+r)>>1;
Build(i<<1,l,mid);
Build(i<<1|1,mid+1,r);
c[i]=c[i<<1]+c[i<<1|1];
}
void pushdown (int i,int l,int r) {
if (lz[i]) {
int mid=(l+r)>>1;
c[i<<1]+=1ll*(mid-l+1)*lz[i];
lz[i<<1]+=lz[i];
c[i<<1|1]+=1ll*(r-mid)*lz[i];
lz[i<<1|1]+=lz[i];
lz[i]=0;
}
}
void up (int i,int l,int r,int L,int R,int v) {
if (l>=L&&r<=R) {
c[i]+=1ll*(r-l+1)*v;
lz[i]+=v;
return;
}
pushdown(i,l,r);
int mid=(l+r)>>1;
if (L<=mid) up(i<<1,l,mid,L,R,v);
if (R>mid) up(i<<1|1,mid+1,r,L,R,v);
c[i]=c[i<<1]+c[i<<1|1];
}
long long query (int i,int l,int r,int L,int R) {
if (l>=L&&r<=R) return c[i];
pushdown(i,l,r);
int mid=(l+r)>>1;
long long ans=0;
if (L<=mid) ans+=query(i<<1,l,mid,L,R);
if (R>mid) ans+=query(i<<1|1,mid+1,r,L,R);
return ans;
}
void dfs (int u,int f) {
dfn[u]=++tol;
cnt[u]+=cnt[f];
id[tol]=u;
sz[u]=1;
for (int v:g[u]) {
if (v==f) continue;
dfs(v,u);
sz[u]+=sz[v];
}
}
int cc[maxn];
int main () {
ios::sync_with_stdio(false);
cin>>q>>n;
if (n==1&&q==1) return printf("1\n"),0;
for (int i=1;i<=n;i++) {
cin>>s;
ed[i]=insert(s);
cc[ed[i]]++;
}
build();
for (int i=1;i<=tot;i++) {
g[fail[i]].push_back(i);
g[i].push_back(fail[i]);
}
dfs(0,0);
Build(1,1,tot+1);
while (q--) {
string op;
cin>>op;
if (op[0]=='?') {
long long ans=0;
int u=0;
for (int i=1;i<op.size();i++) {
u=tr[u][op[i]-'a'];
ans+=query(1,1,tot+1,dfn[u],dfn[u]);
}
printf("%lld\n",ans);
}
else if (op[0]=='+') {
int tt=0;
for (int i=1;i<op.size();i++) {
tt=tt*10+op[i]-'0';
}
if (cc[ed[tt]]) continue;
cc[ed[tt]]++;
up(1,1,tot+1,dfn[ed[tt]],dfn[ed[tt]]+sz[ed[tt]]-1,1);
}
else if (op[0]=='-') {
int tt=0;
for (int i=1;i<op.size();i++) {
tt=tt*10+op[i]-'0';
}
if (cc[ed[tt]]==0) continue;
cc[ed[tt]]--;
up(1,1,tot+1,dfn[ed[tt]],dfn[ed[tt]]+sz[ed[tt]]-1,-1);
}
}
}
原文地址:https://www.cnblogs.com/zhanglichen/p/15006774.html
- 通过top命令抓取cpu高消耗的sql (44天)
- 关于字符串匹配查找的总结(43天)
- 一条sql语句导致的数据库宕机问题及分析(42天)
- 外部表的导入导出问题 (41天)
- 当我们和计算机交互时,它看到的是什么?
- 一条sql语句“导致”的数据库宕机问题及分析 (38天)
- rman数据备份恢复学习笔记(49天)
- 虚拟专用数据库VPD应用 (48天)
- 关于创建视图的问题(48天)
- 性能调优之redo切换频率(47天)
- 关于oracle中session跟踪的总结(56天)
- oracle中关于小数中0的格式化(55天)
- 关于trigger过滤最大值的问题(54天)
- oracle共享服务器配置汇总(53天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 决策树预测成本价 2020年 MathorCup数学建模 A题 无车承运人平台线路定价问题
- 2020年 MathorCup数学建模 A题 无车承运人平台线路定价问题,定价评价
- RabbitMQ 消费端限流、TTL、死信队列
- 全栈必备 Redis基础
- JSP的异常处理
- (二)Mybatis-Plus的安装配置
- 如何在JSP里自定义标签
- 如何在JSP里使用Java bean
- 获取指定时间内指定星期几的所有日期
- 使用JSP的标准标签库JSTL处理XML格式的数据
- (一)初识Mybatis-Plus
- org.apache.tomcat.util.scan.StandardJarScanner找不到serializer.jar的问题
- JAVA中获取当前系统时间
- 使用Supervisor管理进程
- vue 中使用threejs