Mike and Friends(CodeForces - 547E,AC自动机fail树dfs序上建可持久化线段树)

【CodeForces - 163E】:e-Government【AC自动机fail树上dfs序+树状数组】 题目: CodeForces - 163E:e-Government 题意: 给出 K个模式串,N 次操作:(1)删除一个模式串(2)添加一个模式串(K个中的某一个)(3)给出一个主串,问模式串在主串中总共出现了多少次 笔记: fail树: AC自动机上每一个节点都有唯一的fail指针,那么将fail指针逆转后,所有的 fail指针和节点将形成一颗有根树 根据 fail指针的定义... 阅读详情

一、题目链接

Mike and Friends

二、题目大意

有 n n n 个字符串 s 1 , s 2 , ⋯   , s n s_1,s_2,\cdots,s_n s1​,s2​,⋯,sn​ 和 q q q 次询问.

定义函数 f ( S , T ) f(S,T) f(S,T) 为字符串 S S S 在字符串 T T T 中的出现次数.

每次询问给出三个整数 l , r , k l,r,k l,r,k 表示询问 ∑ i = l r f ( s i , s k ) \sum_{i=l}^{r}{f(s_i,s_k)} ∑i=lr​f(si​,sk​).

1 ≤ n ≤ 2 × 1 0 5 , 1 ≤ q ≤ 5 × 1 0 5 , 1 ≤ ∑ ∣ s i ∣ ≤ 2 × 1 0 5 , 1 ≤ l ≤ r ≤ n , 1 ≤ k ≤ n 1 \leq n \leq 2 \times 10^5, 1 \leq q \leq 5 \times 10^5, 1 \leq \sum{|s_i|} \leq 2 \times 10^5, 1 \leq l \leq r \leq n, 1 \leq k \leq n 1≤n≤2×105,1≤q≤5×105,1≤∑∣si​∣≤2×105,1≤l≤r≤n,1≤k≤n.

三、分析

首先考虑一个弱化问题,假设每次询问 l = 1 , r = n l=1,r=n l=1,r=n,即只有 k k k 在变化. 显然,我们可以进行如下预处理:对 n n n 个字符串建立 AC 自动机,在每个字符串的每个前缀对应的字典树节点上 + 1 +1 +1. 查询的答案即为 s k . e n d ( ) s_k.end() sk​.end() 对应字典树节点的fail子树和. 如上问题可使用AC自动机fail树dfs序上建线段树解决.

对于原问题,与弱化问题相比 l , r l,r l,r 都在变化,只需要将线段树升级成可持久化线段树即可.

四、代码实现

#include <bits/stdc++.h>
using namespace std;

const int M = (int)2e5;
const int N = (int)17;

string s[M + 5];

struct Trie {
	int tot;
	int fail[M + 5], q[M + 5], pos[M + 5];
	int nx[M + 5][26], go[M + 5][26];

	void clear() {
		tot = 0;
		memset(nx[tot], 0, sizeof nx[tot]);
	}

	int newnode() {
		++tot;
		memset(nx[tot], 0, sizeof nx[tot]);
		return tot;
	}

	void insert(int id) {
		int u = 0;
		for(int i = 0, v; i < (int)s[id].size(); ++i) {
			v = s[id][i] - 'a';
			if(nx[u][v] == 0) nx[u][v] = newnode();
			u = nx[u][v];
		}
		pos[id] = u;
	}

	void build() {
		int l = 1, r = 0;
		fail[0] = 0;
		for(int i = 0; i < 26; ++i) if(nx[0][i]) {
			go[0][i] = nx[0][i];
			fail[nx[0][i]] = 0;
			q[++r] = nx[0][i];
		} else go[0][i] = 0;
		while(l <= r) {
			int u = q[l++];
			for(int i = 0; i < 26; ++i) if(nx[u][i]) {
				go[u][i] = nx[u][i];
				fail[nx[u][i]] = go[fail[u]][i];
				q[++r] = nx[u][i];
			} else go[u][i] = go[fail[u]][i];
		}
	}

	vector<int> g[M + 5];
	int st[M + 5], en[M + 5], dfn;
	struct segTree {
		int tot;
		int rt[M + 5];
		int lc[2 * M * (N + 1) + M + 5], rc[2 * M * (N + 1) + M + 5];
		int sum[2 * M * (N + 1) + M + 5];

		void clear() {
			tot = 0;
			lc[tot] = 0, rc[tot] = 0;
		}

		void update(int x, int y, int l, int r, int a, int b) {
			if(l == r) return;
			int mid = (l + r) >> 1;
			if(a <= mid) {
				int lcx = lc[x];
				sum[++tot] = sum[lc[x]] + b;
				lc[y] = tot, rc[y] = rc[x];
				update(lcx, lc[y], l, mid, a, b);
			} else {
				int rcx = rc[x];
				sum[++tot] = sum[rc[x]] + b;
				lc[y] = lc[x], rc[y] = tot;
				update(rcx, rc[y], mid + 1, r, a, b);
			}
		}

		int query(int x, int y, int l, int r, int a, int b) {
			if(a <= l && r <= b) return sum[y] - sum[x];
			int mid = (l + r) >> 1, s = 0;
			if(a <= mid) s += query(lc[x], lc[y], l, mid, a, b);
			if(mid < b)  s += query(rc[x], rc[y], mid + 1, r, a, b);
			return s;
		}
	} tr;

	void dfs(int u) {
		st[u] = ++dfn;
		for(const int &v: g[u]) dfs(v);
		en[u] = dfn;
	}

	void gao(int n) {
		for(int i = 0; i <= tot; ++i) g[i].clear();
		for(int i = 1; i <= tot; ++i) g[fail[i]].push_back(i);
		dfn = 0; dfs(0);
		for(int i = 0; i < n; ++i) {
			tr.rt[i + 1] = ++tr.tot;
			for(int j = 0, u = 0; j < (int)s[i].size(); ++j) {
				u = go[u][s[i][j] - 'a'];
				if(j == 0) tr.update(tr.rt[i], tr.rt[i + 1], 1, tot + 1, st[u], 1);
				else tr.update(tr.rt[i + 1], tr.rt[i + 1], 1, tot + 1, st[u], 1);
			}
		}
	}

	int query(int l, int r, int k) {
		return tr.query(tr.rt[l - 1], tr.rt[r], 1, tot + 1, st[pos[k - 1]], en[pos[k - 1]]);
	}
} trie;

void work() {
	int n, q; cin >> n >> q;
	trie.clear();
	for(int i = 0; i < n; ++i) {
		cin >> s[i];
		trie.insert(i);
	}
	trie.build();
	trie.gao(n);
	for(int i = 0, l, r, k; i < q; ++i) {
		cin >> l >> r >> k;
		cout << trie.query(l, r, k) << "\n";
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	work();
	return 0;
}

模板 - AC自动机 AC自动机模板 阅读详情

相关推荐

宇树机器人丝滑的二人转动作背后,MPC到底是什么?

了解MPC,让我们闻“机”起舞。

Barok的博客 2144

ac自动机fail树上dfs序建可持久化线段树

#include <cstring> #include <cstdio> #define max(a,b) a>b?a:b const int mn=300005; struct Trie{ int father,fail,next[26]; void init(){ father=fail=0; memset(next,0,sizeof next);...

冷月寒笙的博客 1824

ThingsBoard实战指南:RPC命令下发与设备交互详解

本文深入解析了ThingsBoard平台中RPC命令下发的核心机制与实战应用。通过对比客户端与服务端RPC模式,详细阐述了从仪表盘控件配置到设备端Python代码响应的完整双向交互流程,并提供了常见问题排查与进阶优化技巧,帮助开发者构建可靠、实时的物联网设备控制系统。

weixin_29168153的博客 213

AC自动机算法模板

PS:还不是很会,上午刚学,把仅学的一点先记录下来,肯定有错,学会了再来纠正(逃。 测试题目:http://acm.hdu.edu.cn/showproblem.php?pid=2222 想学自动AC机,忽然发现当初最开始学习时听到的一句话如今真的学到这里了:AC自动机fail树上dfs序建可持久化线段树。嘤 AC自动机 = KMP + Trie时间复杂度O((n+m)*L) 具体思想,...

nEo.大魔王 1035

ANSYS_APDL实战入门——从零开始掌握模态分析

本文为ANSYS APDL模态分析实战入门指南,通过一个悬臂梁案例,手把手教你从零开始掌握APDL命令流。内容涵盖从模型创建、材料定义、网格划分到边界条件设置、求解及后处理结果查看的全流程,帮助工程师快速上手结构动力学分析,避免共振风险。

egg99的博客 1130

微信聊天记录解密,必须是root的手机

手机上安装x-plore软件,将/data/data目录的相关EnMicroMsg.db auth_info_key_prefs.xml拷贝到/storge/emulated/0目录后才可以拷贝到电脑。路径:/data/data/com.tencent.mm/shared_prefs/auth_info_key_prefs.xml。但是是加密过的 需要解密 解密密码生成规则是手机IMEI+微信UIN md5(32位小写)后的前7位。安卓手机要root测试版本微信要7或者8版本都可以。选择message表。

venus60的专栏 1007

CF 163E //AC自动机fail树上建线段树 || 建树状数组+差分

题目 题意 n(1e6)n(1e6)n(1e6)个询问,kkk个模式串(总长度(1e6)(1e6)(1e6))。 询问: 1:给定串sss求,sss串里模式串出现几次。 2:将第iii个串删除(若已经删除无视此操作。 2:将第iii个串恢复(若已经存在无视此操作。 思路 建立AC自动机,在fail树上,用当前结点去更新后代。 可以在fail树上先序dfs序dfs序dfs序上维护线段树(区间更新,单...

Rshs 1338

18650锂电池充放电测试全流程:从实验室到实际应用的避坑指南

本文详细介绍了18650锂电池充放电测试的全流程,从实验室设备选型到实际应用中的常见问题解决方案。涵盖测试前的准备工作、标准测试流程执行、动态工况测试以及数据深度分析方法,为电池测试工程师和科研人员提供实用的避坑指南。特别针对电压平台异常和温度异常等关键问题,提供了专业的诊断与解决措施。

weixin_30790841的博客 546

uva11481

此题纠结了我一段时间了。今天在acseed的提示下我ac了。。 首先题目很容易就可以想到首先算出前面C(m,k)种方案。那么就要考虑其他的n-k个位置都要不在其位置上。 那么我首先想到了错排。但是不知道为什么如果这么算的话是错误的。以5,3,2为例,答案是12,但是用错排算却是6错的。我就不知道为什么了。 求大神指教我上面的想法为什么错了啊。 然后被提醒说是容斥原理,首先第一步还是C(m,

lyc 933

Arm Neoverse CMN-700 SLC内存系统与缓存分区技术解析

现代处理器架构中,缓存一致性协议与内存子系统设计直接影响系统性能。Arm Neoverse CMN-700采用的SLC(System Level Cache)通过16-way组相联设计实现高效数据缓存,其物理地址索引机制支持灵活的way分区配置。在软件可配置内存(OCM)模式下,SLC可作为独立内存空间使用,通过寄存器控制实现模式切换与区域锁定。缓存分区技术则通过请求源分类和way-based分配策略,满足实时性任务与吞吐量场景的不同需求。这些技术在5G基站、边缘计算等低延迟场景中具有重要应用价值,特别是C

weixin_30263073的博客 618

Zynq AXI DMA实战:5分钟搞懂S_AXIS_S2MM和M_AXIS_MM2S数据流(附Vivado配置截图)

本文通过Vivado实战配置,清晰解析了Zynq平台AXI DMA IP核中S_AXIS_S2MM和M_AXIS_MM2S数据流的核心概念与连接方法。文章重点阐述了数据流向、主从关系及接口命名规则,并提供了从ADC数据采集到DDR存储,再从DDR读取数据发送至DAC的完整双向数据流搭建指南,帮助工程师快速避坑。

weixin_29200741的博客 451

【模板】AC自动机

ACM模板 目录插入以及构建AC自动机【模板】AC自动机(二次加强版)ac自动机fail树上dfs序建可持久化线段树 插入以及构建AC自动机 #include<queue> #include<string> const int N=200010; struct node { int chd[26],fail,cnt; }tree[N]; void insert(string s) { int p=0; for(int i=0;i<s.size();i+

Fighting_Peter的博客 399

精度与速度双突破:YOLOv8-Pose 在 RK3588 上实现高性能人体姿态分析部署

本教程从YOLOv8-pose模型的姿态识别训练,到RK3588的边缘量化部署,为你打造了一套“高精度+高实时性+低成本”的人体姿态分析解决方案。无论是健身动作纠正、智能安防行为检测,还是工业人员姿态监控,这套技术都能直接复用——你只需替换数据集与业务逻辑,即可快速落地专属的边缘AI姿态识别系统。如果你在实践中遇到任何卡点,欢迎随时交流。记住,人体姿态识别的价值在于“关键点准、推理快、部署易”,而这三者的平衡,正是你通过本教程能掌握的核心能力。

know_F0727的博客 434

Codeforces Round #305 (Div. 1)E. Mike and Friends(AC自动机+fail树dfs序+主席树)

传送门 题意:给定n个字符串,q次询问,每次给出正整数L,R,X,要求输出第x个字符串在第l个字符串到第r个字符串的总匹配次数。 (字符串长度之和不大于2e5) 分析: 首先我们考虑对于一个字符串集合,我们如何求出其中某个字符串在集合中的匹配次数?比如给定集合cacaa,baabaa,aa。求出aa在集合中的总匹配次数。(易知答案是4) 。 我们可以把所有的串插入AC自动机,再用aa去trie树上匹配,随后统计fail树上每个子树的点权和。 aa的尾节点的匹配次数就是答案了。 为什么呢?因为在fail树

矮纸斜行闲作草 277

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

CodeForces 547E Mike and Friends AC自动机 主席树

题意: 给出\(n\)个字符串\(s_i\)和\(q\)个询问: \(l,r,k\):\(\sum\limits_{i=l}^{r}count(i, k)\),其中\(count(i,j)\)表示\(s_j\)作为子串在\(s_i\)中出现的次数 分析: 先不考虑查询中\(l,r\)的限制,考虑该字符串\(s_k\)在一个字符串集合中出现的次数。 先将这个字符串集合插入到一棵Trie数中,并且...

weixin_30379911的博客 93

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

codeforces #305 E Mike and friends

原问题可以转化为:给定第k个字符串,求它在L-R的字符串里作为子串出现了多少次 定义子串为字符串的某个前缀的某个后缀(废话) 等价于我们把一个字符串插入到trie里,其过程中每个经过的节点和其向上的fail链上的点都是该字符串的子串 又因为对于一条fail链,u向上能访问到v当前仅当u在v的子树内 那么原问题又变成了: 将L-R个字符串按照上述方法插入到trie中并将经过的节点...

weixin_30549657的博客 88

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

bzoj3881 [Coci2015]Divljak(AC自动机+fail树+dfs序+树状数组+树链剖分)

bzoj3881 [Coci2015]Divljak 原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3881 题意: Alice有n个字符串S1,S2...Sn" role="presentation" style="position: relative;">S1,S2...SnS1,S2...SnS_1,S_2...S_n,Bob

Bfk的博客 1145

C - Permutation Counting UVALive - 5092 dp

题目链接 题意: 给出n和m,我们有一个由1~n组成的n个数字的数列a[],如果a[i]>i,我们就把ans++,我们要求出ans==m的数列有多少个。 思路: 直接按照dp的思想,我们考虑每增加一个数那么它只会是E-VAL的值要么不变 要么增加1 那么dp[i][j]就表示第i个数j E-val 的数列个数,可得出此动态转移方程 dp[i][j]=(dp[i][j]+(j+1)*

Marcus-Bao的个人主页 521

[COCI2015]Divljak

题目大意 有 nnn 个字符串 S1,S2,⋯ ,SnS_1, S_2, \cdots, S_nS1​,S2​,⋯,Sn​ 和一个字符串集合 TTT,一开始 TTT 为空。 然后有两个操作: 1 P 往 TTT 里加一个字符串 PPP。 2 x 询问集合 TTT 中有多少个字符串包含串 SxS_xSx​ (我们称串 AAA 包含串 BBB,当且仅当 BBB 是 AAA 的子串)。 对于 100%100\%100% 的数据,1≤n,q≤1051 \leq n,q \leq 10^51≤n,q≤105,字符

orz 232

CodeForces - 547E Mike and Friends

题意: 给定 nnn 个由小写字母组成的字符串,qqq 次询问,每次询问 l,r,kl, r, kl,r,k,表示求 sks_ksk​ 在 sl,sl+1,⋯ ,srs_l, s_{l+1}, \cdots, s_rsl​,sl+1​,⋯,sr​ 中出现的次数。(n,q≤2×105)(n, q \leq 2×10^5)(n,q≤2×105) 链接: https://vjudge.net/probl...

weixin_44059127的博客 285

机器学习模型的本质:数据驱动的条件反射协议

机器学习模型并非具备认知能力的智能体,而是一种基于统计相关性的输入-输出映射机制。其核心原理是通过海量数据拟合特征与目标间的数学关系,形成稳定但脆弱的‘条件反射协议’。这种协议高度依赖数据分布一致性,一旦遭遇概念漂移、分布偏移或特征泄露,性能便急剧衰减。技术价值在于将业务规则转化为可计算、可监控、可迭代的工程化组件;典型应用场景覆盖智能风控、工业质检、推荐系统与医疗辅助决策等关键领域。本文深入剖析模型的四层架构、生命周期管理及真实落地中的隐性陷阱,直击‘能跑通却不敢上线’的核心痛点。

weixin_30596343的博客 232

Codeforces 547E

不明白这个题为啥会是div1E。。。 套路的,给所有串建个AC自动机,插入的时候给路径打标记,这样统计一个串在[l,r][l,r][l,r]中出现了多少次就等价于统计在这个点fail树的子树中有多少个[l,r][l,r][l,r]间的标记,直接将询问离线后扫描线,对dfs序用树状数组维护即可。 时间复杂度O((∑i=1n∣si∣+q)log⁡n)\mathcal O((\sum_{i=1}^{n}...

mayaohua 308

【题解】Codeforces 963D. Frequency of String AC自动机

给定字符串S(1e5)S(1e5)S(1e5),有q(1e5)q(1e5)q(1e5)个询问,每次给定一个整数kik_iki​和字符串mim_imi​。 让你从SSS中选择一个子串TTT,且mim_imi​在TTT中出现了至少kik_iki​次。 保证mim_imi​的长度之和不超过1e51e51e5,保证所有的mim_imi​不相同。 这道题的关键在最后的两个保证上。 使用AC自动机可以求得所......

秋叶红于二月花 682

Codeforces 163E (AC自动机&fail树+dfs序+树状数组)

http://codeforces.com/contest/163/problem/E 实在不好意思,自己画的时候确实有点粗心,感谢大家的提醒。。这次图应该画对了。。 题意:给你几个串,然后后面有些操作,分别是给你一个文本串问哪些模式串在文本串出现了多少次,剩下两个分别就是删除一些字符串,和恢复一些字符串。 做法:AC自动机,(据说还有后缀数组。。不会),如果做过阿狸的打字机这道题应该知道怎...

KXL5180的博客 519

Codeforces AC自动机 题目汇总

86C codeforces 149E. Martian Strings 163E 291E

qq_39898877的博客 700

HDU - 4117 GRE Words (AC自动机+Fail树+线段树+DFS序+DP)

GRE Words Problem Description Recently George is preparing for the Graduate Record Examinations (GRE for short). Obviously the most important thing is reciting the words. Now George is workin

LP_Cong 3604
上一篇: SDNU_LqbTraining_2022_1【解题报告】
下一篇: CTF之MISC常用工具
The___Flash
博客等级 码龄8年 79粉丝 223原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值