Chelly的串串专题
CF149E
题意:给出一个长度为n的文本串和m个模式串,求有多少个模式串可以拆成两半,使得这两半按顺序匹配(n<=2e5,m<=100)
最暴力的想法就是对于每个询问串,全部和原串做一遍kmp,求出每个前缀/后缀在原串中被匹配到的最前/最后位置,但这样对于每组询问都需要遍历文本串一遍
可以考虑对文本串建立SAM,对于每个节点我们可以求出其endpos中的最小值,然后对于每组询问串,直接在SAM上走即可
时间复杂度\(O(n+\sum |T| )\)
CF223B
题意:给你两个字符串S,T。将S中所有的子序列(要求这些子序列和T串相同)染色,最后问你能否将S染全,即每个字符都会染到
对于S中的每个位置考虑其能否被染到,即是判断能否在左边找到一个子序列,在右边找到一个子序列,和它自己拼起来正好是T串
于是可以从左到右求出以i为子序列的最后一个位置,最远可以匹配到T的哪里;从右到左求出以i为子序列最后一个位置,最远可以匹配到T的哪里
最后对于每个位置判断一下这个东西是否交叉即可
CF291E
题意:一棵树,每条边上有一些字符,求目标串出现了多少次到
很显然的做法是一边dfs一边kmp,但是这样会被卡掉,因为在有撤销/回退情况下,kmp会被卡到平方级别,所以我们提前把kmp补全成自动机即可。
CF645E
题意:字符集大小为k,有一个初始串S,你需要在后面接上一个长度为n的字符串,使得最终字符串本质不同的子序列个数最多
先考虑对于一个固定字符串,如何求它的本质不同子序列个数
设\(dp[i]\)表示前i个位置的本质不同子序列个数
那么\(dp[i]=2 \times dp[i-1] - dp[pre[s[i]]-1]\)
现在考虑后面的n个位置,显然\(dp[i]\)是单调递增的,所以每次选择的\(pre[s[i]]-1]\)尽可能小即可
CF316G
题意:有10个限制(p,l,r),若一个字符串t满足在p中出现次数在\([l,r]\)之间,那么则称字符串t满足该限制。现在给一个字符串s,问它有多少个本质不同的子串满足所有10个限制。所有字符串长度<=50000
对于11个母串建立广义后缀自动机,然后再拓扑排序即可求出广义后缀自动机上每个节点在各自母串中的出现次数,最后扫一遍即可判断
CF868D
题意:有n个字符串,m次操作,每次操作把两个字符串拼在一起,并询问这个新串的价值。定义一个新串的价值k为:最大的k,使得这个新串包含所有长度为k的01串(这样的字符串有\(2^k\)个)
首先考虑k最大有多少,因为每次合并两个已有字符串,可能造成额外贡献的长度为k的字符串最多只有k个,而最多只会经过100次合并,所以列出不等式可以知道k最大为10
也就是说虽然后面的字符串会很长,但我们只需要记录下他长度为10的前后缀即可处理合并的贡献,至于内部的贡献我们可以递归下去求
注意这个递归不是指数级的,因为可能会重复求解一个前面字符串本身,所以我们可以记忆化一下,这个递归就是线性的了
CF965E
题意:有n个字符串,对于每个字符串你可以挑一个前缀来代表它,但两个不同的字符串的代表前缀不能一样。现在你需要找出每个字符串的满足要求的代表前缀,并且让他们的长度总和最短。
将所有字符串建成一个Trie,然后先构造出一组可行解,也就是那些表示单词的节点
然后每次贪心选择一个深度最大的点尽可能往上移,用并查集加速
CF895D
题意:给定两个长度都为n的字符串a和b,保证a字典序小于b。问有多少个字符串c满足以下要求:(1)c字典序大于a,c字典序小于b (2)c中每个字母的出现次数与a中一模一样
ans=solve(b)-solve(a)-1
solve(b)指的是有多少个字符串字典序严格小于b
那么只需要O(n)枚举第一个不同的位置在哪里然后去计数即可
CF566A
题意:有一个完全二分图,左边n个点,右边n个点,每个点都有一个字符串,一条边权等于其所连接两点的字符串的最长公共前缀,求最优匹配。
将右边的字符串建成Trie树,然后左边的按照一定顺序在Trie上匹配
那么按照什么顺序呢?
显然,我们肯定优先选择目前能在Trie树上匹配深度最多的字符串进行优先匹配;注意我们完成一次匹配之后,Trie树形态会改变,所以每个点在Trie树上能匹配到的最深位置是会改变的,需要动态去维护。
CF1017E
题意:给两个凸包,问它们能否通过平移和旋转同构。
按顺序求出它们的边长序列和角度序列,看是否循环同构即可(KMP或者哈希)
对于角度序列,注意到不能用叉积来判断,因为叉积的本质是\(sin(x)\),这个函数在\([0, \pi]\)中不是单调的
所以要利用点积求出该角的\(cos\)值
CF17E
题意:给一个字符串,求有多少对相交的回文子串,答案对质数取模。
考虑求反面,求出有多少对回文子串是不相交的
正反两边回文树求出以i结束的回文子串个数,以i开头的回文子串个数
然后后面做个后缀和,枚举前面的回文子串,就能求出来不相交的对数
但这题卡空间,于是要用马拉车解决这个问题
首先通过马拉车求出以i为结束的回文子串个数,然后枚举i,计算以i为回文中心的回文串的贡献,很明显这是一个前缀和的区间和,可以前缀和再前缀和维护一下到O(n)复杂度