字符串—KMP/AC自动机
#
夕林山寸
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
2020牛客暑期多校训练营(第二场) A All with Pairs KMP+hash
题目求的是前缀与后缀匹配长度平方和。 由于后缀总共就1e6个。 所以我们可以用hash把后缀存下来。 然后枚举每个串的前缀,计算f(s,t)^2. 但这样会重复: 比如 : ab ba aba 枚举s为aba时当t是aba时,a计算了一次,ab也计算了一次,aba又计算了一次。 所以我们从前往后枚举s串的前缀时,要减去与当前 前缀匹配的后缀,与之前前缀匹配的结果。 比如: s为aba时。 枚举到a,有ba,aba 的后缀与它匹配 ,ans+= 2* 1*1; 枚举到ab,有...原创 2020-09-02 17:02:50 · 168 阅读 · 0 评论 -
2020牛客暑期多校训练营(第二场) A All with Pairs AC自动机 fail树上处理
有一个比较显然的思路: 先把每个串插入到字典树中建立AC自动机 枚举每个字符串做为t串,求f(s,t),我们知道AC自动机上fail[i]即:根节点到i节点路径上字符串最长的(当前字符串的后缀)与模式串的前缀匹配。类似于于KMP里的next。所以枚举了一个字符串t,s串一定在t串结尾字符节点u的fail树祖先链上。 我们沿fail树链求贡献即可。 但有个问题: 上图是样例的字典树,红线是fail数组。 绿线枚举t串为aba时,遍历6号节点的fail树链。 贡献为: 在6号节点,有3*3=9原创 2020-09-01 21:14:51 · 204 阅读 · 0 评论 -
P4052 [JSOI2007]文本生成器 AC自动机 fail树上跑DP
//int dp[2][107][6007];// i为0/1是否满足出现一个模式串, 处理到第j位, 处于AC自动机第j号节点 的方案数 建立fail树,类似AC自动机跑文本串的方法转移DP。 v=tr[u][j]; 由于每个点连向j字符的点唯一,所以构造m长度的字符串后,停留在j点的方案数一定是不重复的,最终的方案数就是 停留在所有节点构造出长度为m的字符串方案数总和。 转移就是简单的dp转移。 注意flag[i]表示构造到第i号节点,所组成的字符串是否出现过模式串。即相当于跑到每个节点,..原创 2020-09-01 17:05:27 · 231 阅读 · 0 评论 -
Computer Virus on Planet Pandora HDU - 3695 文本串正反跑一遍AC自动机
显然我们直接让文本串正反各跑一遍AC自动机更加方便。 只是问模式串在AC自动机出现次数,所以直接消去flag标记即可。 #include <cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; typedef long long ll; #define re register #define l原创 2020-08-31 16:53:40 · 174 阅读 · 0 评论 -
病毒侵袭 HDU - 2896 AC自动机
AC自动机基础题, 每个字符存一下是哪几个病毒的结尾字符。 然后查询时直接存下来即可。 注意每次flag要重新更新。 #include <cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; typedef long long ll; #defi原创 2020-08-29 16:49:00 · 169 阅读 · 0 评论 -
P3808 【模板】AC自动机(简单版)
给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。 注意:是出现过,就是出现多次只算一次。 AC自动机步骤: 1:处理所有模式串,建立trie树: 2:处理fail[i]数组:(最长的(当前字符串的后缀))在Trie上可以查找到)的末尾编号。 显然fail[i]的深度一定小于i,所以可以BFS递推fail数组。 而根据fail数组的定义,对于一个点u,他的fail数组求出过了,对于他的儿子v节点(是u指向i字符的儿子),若v存在,则v的fail为:tr[fail[u]][i] 若v原创 2020-08-29 16:24:40 · 277 阅读 · 0 评论 -
Om Nom and Necklace CodeForces - 526D KMP处理循环节 + 数学取整运算证明
题意:求每个前缀是否是ABABA 的形式。(其中A有k+1个,B有k个,AB均可为空) 对于一个前缀字符串i: 令S=AB 则可看成:SSSSA。 若满足S的个数为k,则满足题意。 对于前缀字符串i:其最小循环节e长度为:i-nxt[i], 改字符串可以看做:eeeex 如果若干个e拼凑成一个S,使得S的数量为k,则满足题意。 最后的x和前面若干个e组成A。 具体判断的话我们可以分情况: 下面是官方题解 #include <bits/stdc++.h> using原创 2020-08-28 16:38:42 · 287 阅读 · 0 评论 -
Simpsons’ Hidden Talents HDU - 2594 连接串跑KMP
问s1前缀与s2后缀最大匹配。 显然拼接两个串,然后跑KMP,(中间用分隔符,防止结果大于n) #include<cstring> #include<iostream> #include<vector> using namespace std; typedef long long ll; const int M = 1e6+7; char p[M],t[M]; int nxt[M]; int main() { ios::sync_with_stdio(false原创 2020-08-27 13:35:47 · 157 阅读 · 0 评论 -
Seek the Name, Seek the Fame POJ - 2752 KMP水题
根据nxt数组的定义,就是前缀等于后缀最大的子串长度。 for一遍也行,while(nxt[tp])也行。 KMP这种东西尽量每次都手敲吧,最基础的算法没必要套板子 #include<cstring> #include<iostream> #include<vector> using namespace std; typedef long long ll; const int M = 1e6+7; struct KMP { char p[M],t[M];//模原创 2020-08-27 13:28:25 · 187 阅读 · 0 评论 -
Power Strings POJ - 2406 最小循环节长度
如果n%(n-nxt[n])==0,那么每一段len 都是相等的(根据kmp nxt数组的含义) #include<cstring> #include<iostream> using namespace std; typedef long long ll; const int M = 1e6+7; struct KMP { char p[M],t[M];//模式串p,文本串t,p在t中出现次数,及位置, 下标1-n int nxt[M],n,m,f[M];//...原创 2020-08-27 13:13:32 · 239 阅读 · 0 评论 -
P3375 【模板】KMP字符串匹配 KMP 模板
好久没做KMP/AC自动机的题了,都快忘了。 就多校HDU做了一道,还是直接套的板子。 这次准备手敲KMP/AC自动机,弄熟悉一点,做点经典题目。 看了5min的B站KMP视频,手敲了板子一遍过。(现在的算法理解能力比之前快多了) 回顾下KMP的算法吧: 首先暴力的话: 枚举文本串p所有位置(长度m),每个位置用模式串匹配(长度n)。复杂度n*m。 而我们发现: 形如:p: abababac, t=ababa时,暴力匹配非常低效 因为我们在匹配p,和t时有很多额外信息被浪费了。 我们...原创 2020-08-27 12:50:10 · 282 阅读 · 0 评论
分享