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自动机模板 阅读详情

相关推荐

【芯片验证随心记】1.SystemVerilog中,rand和randc的区别?如何用constraint实现randc?

在SystemVerilog里,randc 的“不重复循环”特性是用一个 周期性排列器(permutation engine) 实现的,而这个引擎在 LRM 里并没有公开。我们只能在 “用户空间” 用 rand + constraint 去模仿它的行为。每次随机化只取 queue.pop_front(),用完再洗。在4次随机化内,y会依次出现0,1,2,3各一次(顺序随机)每次随机化,x可能是0-3中的任意值,可能连续多次相同。每次随机化时,在未使用的值里随机挑一个;第5次随机化时,重新生成新的排列周期。

qq_43172512的博客 342

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

来!简单了解一下计算机发展史!

​ 1936年,英国数学家阿兰・麦席森・图灵提出了一种抽象的计算模型——图灵机( Turing machine)。图灵机,又称图灵计算机,即将人们使用纸笔进行数学运算的过程进行抽象,由一个虚拟的机器替代人类进行数学运算。​ 图灵机是一个抽象的机器,它有一条无限长的纸带,纸带分成了一个一个的小方格,每个方格有不同的颜色。有一个机器头在纸带上移来移去。机器头有一组内部状态,还有一些固定的程序。

m0_57290404的博客 2907

AC自动机算法模板

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

nEo.大魔王 1035

Python时间序列:PaddleTS-时间序列分类

评估的指标采用F1,Precision,Recall,PaddleTS已经基于TSDataset实现了这三个指标的计算,直接调用即可。使用内置的API:get_dataset加载BasicMotions数据集。模型训练完成之后,可以对测试集进行预测并评估。模型保存之后,可以加载模型用于新的数据预测。可以将训练完成的模型保存到指定路径。概率预测 可以返回每个分类的概率。安装paddlets。

斌擎科技 1293

在 VS Code 里配置 SAP Joule for Developers 的 ABAP AI side-by-side 能力

摘要: 随着ABAP开发工具链的演进,VS Code逐渐融入ABAP开发流程,SAP Joule for Developers的ABAP AI能力通过side-by-side模式(基于BTP中央服务)为多系统开发提供统一AI支持。该模式避免了各ABAP后端独立升级AI能力的碎片化问题,由管理员配置BTP订阅URL后,开发者可在ADT或VS Code中全局调用。实际落地需注意角色分工(管理员配置服务,开发者填写URL)、AI units资源规划及配置细节(如区分全局与项目级设置)。建议将Joule URL纳入

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 120

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

ICC2:使用analyze_lib_cell_placement检查lib cell的pass rate

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?在place之前需要使analyze_lib_cell_placement命令去检查lib cell在当前的site row/power plan/legalize设置的环境下能够正常place和legalize。下面分享一个脚本去报告pass rate低于2%的lib cell。

m0_61544122的博客 675

uva11481

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

lyc 933

UG\NX二次开发 获取对象的引用集

获取对象的引用集,一个对象可能有多个引用集,下面这个封装函数可以获取对象的所有引用集。

王牌飞行员_里海的博客 489

如何解决群晖Docker注册表查询失败/无法拉取镜像等问题

如何解决群晖Docker注册表查询失败/无法拉取镜像等问题

XiaoqiangClub的博客 1万+

【模板】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

Allegro如何导出和导入器件模型Signal_Model操作指导

在用Allegro做PCB设计的时候,通常需要给器件加上Signal_Model,在做等长的时候用到的非常频繁。如下图,需要把R7002的Signal_Model导入到另外一块没有给R7002加好模型的BRD中。Allegro除了可以给器件添加模型,还支持从一块加好模型的BRD导入到另外一块BRD中,如何导出和导入器件模型Signal_Model操作指导。

weixin_54787054的博客 1896

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

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

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

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

codeforces #305 E Mike and friends

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

weixin_30549657的博客 88

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

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 231

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、付费专栏及课程。

余额充值