Trie
BZOJ 3689 异或之
大意:
给定n个数,求这n个数两两异或的值中的前k小
解:
将加法换成异或就变成了一个用堆合并多个有序表的经典问题,对于加法我们按大小排序就能得到有序表,而由于这里是异或,我们需要高效地维护有序表,即对于一个数ai快速求出与它异或第k小的数。
我们将所有数按二进制建成Trie,然后在Trie的结点上记录下子树中的结束结点个数,再在Trie树上走一遍就得到了答案
BZOJ 3439 Kpm的MC密码
大意:
给定n个字符串,对于每个字符串求以这个字符串为后缀的字符串中第k小的编号
解:
反转建出字典树,相当于询问这个点的子树里结束结点编号的第k大,子树查询利用dfs转区间第k大,主席树即可
BZOJ 3217 ALOEXT
大意:
维护一个序列,支持以下操作:
1.在某个位置插入一个数
2.删除某个位置上的数
3.修改某个位置上的数
4.求某段区间中的次大值与区间中另一个数的异或值的最大值
解:
假如是询问整个序列,我们可以用字典树来做,由于每次询问区间不一样,我们用平衡树套字典树维护区间信息,这里用替罪羊来套字典树
AC自动机/KMP
BZOJ 3670 NOI2014 动物园
大意:
给一个字符串S(|S|<=106),求所有前缀Si的numi之积,numi为Si的前缀S′的数量,使得该前缀S′与Si的后缀相同且不重叠
解:
类比KMP求fail数组的算法,我们可以在线性的时间内求出每个位置的最长不重叠的与后缀相同的前缀的结束位置,做法一样。然后我们记录一下每个位置有多少个前缀与后缀相同即可。
BZOJ 1355 Baltic2009 Radio Transmission
大意:
给一个循环产生的字符串,求最小循环节
解:
脑补一下可以发现答案就是n?fail[n]
首先这一定是一个合法的解
其次一定不存在更小的循环节,否则fail[n]会更小
因此这就是最小循环节的长度
BZOJ 1009 HNOI2008 GT考试
大意:
给定长度为m的数字串S,求不包含子串S的长度为n的数字串T的数量
解:
这种计数问题我们考虑dp来解决,设计状态时我们发现除了需要知道当前是T的第几位,还需要知道当前的T与S的匹配情况,因为此我们记状态f[i][j]为T的第i位,与S长度为j的前缀匹配,那么转移应该是枚举下一位填充的字符ch转移到f[i+1][j′],我们需要快速的知道对于某个Sj在之后多了一个字符ch将与哪个前缀匹配,这其实就是字符串的匹配问题,由于只有一个模板串,我们用kmp解决。最后我们发现对于任意的i,i?>i+1的转移对于第二维是不变的,因此我们矩阵乘法加速这一过程
BZOJ 1100 POI2007 对称轴osi
大意:
给定一个多边形,求对称轴数量
解:
这里要用到一个神奇的想法。
对于一个多边形,我们先找到它的中心,然后我们就可以将这个多边形序列化,具体做法是这样:任选一个顶点i,与中心O的连线Oi的长度作为序列的第一个元素,顺时针取下一个顶点i+1,取Oi与Oi+1的夹角为第二个元素,Oi+1的长度为第三个元素,然后这样边角边角的不断循环取遍所有定点就得到了一个序列
我们先顺时针得到一个序列并将将序列倍增。再逆时针扫得到另一个序列,逆时针序列在顺时针序列中的出现次数就是对称轴数量,这个问题我们可以用kmp解决
BZOJ 3620 似乎在梦中见过的样子
大意:
给定一个字符串,求这个字符串有多少个子串满足这个子串可以拆分成ABA的形式,其中|A|>=k,|B|>=1
解:
这种前缀与后缀相同很容易使我们联想到kmp
枚举一个子串的左端点,对于一个右端点,我们只需要判断它是否存在长度在[k,2×(|S|?1)]之间的前缀与后缀匹配,那我们求出长度不超过上界的最长前后缀,判断是否满足下界即可
BZOJ 1212 HNOI2004 L语言
大意:
给定一个单词表和m个字符串,问每个字符串的最长的前缀,满足这个前缀可以拆分成一些字符串 使这些字符串都在单词表中出现过
解:
对每个字符串我们考虑dp,记f[i]表示长度为i的前缀能否成功拆分,那么关键问题在于找出所有以i为结尾所出现的单词。
我们将所有单词建成AC自动机,在表示单词结尾的结点上记录单词的长度,将一个串放在自动机上运行,一旦我们转移到一个表示单词结尾的结点,我们就找到了当前位能匹配的最长单词,沿fail一路往上就能找到当前位结束的所有单词,然后处理dp即可。
BZOJ 2434 NOI2011 阿狸的打字机
大意:
初始字串为空,首先给定一系列操作序列,有三种操作:
1.在结尾加一个字符
2.在结尾删除一个字符
3.打印当前字串
然后多次询问第x个打印的字串在第y个打印的字串中出现了几次
解:
首先我们将所有打印的字符串建AC自动机,考虑自动机的fail树,字符串y在自动机上表示为一些结点,对于每个结点,假如它能够通过不断地沿fail树往上走到达x的结束结点,那么x就出现了一次。
那么现在问题就变为,在fail树中求一个点的子树中某个串的结点一共有几个。
子树查询我们考虑dfs序转化为区间查询,那么我们相当于是要询x对应的区间里有几个y
我们离线处理这个问题,并反过来这样想:我们在序列里将y对应的结点都标注为1,然后再处理所有有关y的询问。
这一过程我们可以dfs和树状数组维护。
BZOJ 1030 JSOI2007 文本生成器
大意:
给定n个模式串,求长度为m的至少含有一个模式串的字符串共有多少种
解:
由于是至少一个,直接统计会面临去重的麻烦,因此我们运用补集转化思想,统计一个都不包含的数量。
记dp[i][j]为前i位对于自动机上结点j的方案数,相当于是统计在自动机上走m步而不经过结束结点的路径条数
BZOJ 3172 Tjoi2013 单词
大意:
给定一个n个单词的文章,求每个单词在文章中的出现次数
解:
将所有单词建成AC自动机,考虑它的fail树,我们就是要询问一个单词的结束结点的子树中的所有结点被单词覆盖的次数之和,随便树形dp即可
BZOJ 2754 SCOI2012 喵星球上的点名
大意:
给定n个目标串和m个模式串,问这m个模式串每个在多少个目标串中出现过,以及n个目标串每个以最多多少个模式串为子串
解:
将所有串都扔进AC自动机里,考虑fail树,我们就是要询问每个模式串的结束结点的子树里的所有结点是多少个不同的目标串的前缀,我们在每个结点上开一个set,然后启发式合并即可,第二问合并的时候顺手统计了就可以
BZOJ 2553 BeiJing2011 禁忌
大意:
给定n个模式串,定义一个字符串的伤害为所有子串的划分中最多包含的模式串数量,求长度为len的字符串的伤害期望值
解:
首先建立AC自动机 令f[i][j]表示长度为i的字符串在AC自动机上的第j个节点的伤害期望值。
如果要走到某个节点是危险节点或者fail指针指向危险节点,就ans++,然后回到根节点,容易知道贪心地这样走一定是符合最多包含的要求的。
这时候直接用快速幂加速我们没法统计答案,因此我们开一个计数器,新增一个结点new,一旦需要ans++的时候就向new转移1,再添加一个new的自环,使答案能累计起来
BZOJ 3881 Coci2015 Divljak
大意:
给定两个字符串集合S和T,初始给定S集合中的所有字符串,不断向T集合中添加字符串,以及询问S集合中的某个字符串在T集合中的多少个字符串中出现过
解:
假如T是不变的,那我们把S和T都扔进AC自动里随便统计一下就行了,而T在改变,相当于我们每次把新字符串扔进自动机里跑,跑到的结点塞一个新字符串,然后再询问某个S的结束结点的fail树中的子树的所有结点的不同字符串数量。
这个问题有很多做法,一种做法是利用树链的并,我们跑到的所有结点直接将它到根的路径上的所有点++,对于很多这样的结点就有很多条路径,我们将这些路径求并(因为同一个串只计算一次)即可。
BZOJ 1444 JSOI2009 有趣的游戏
大意:
给定n个长度为l的模式串,现在要用前m个大写字母生成一个随机串,每个字符有自己的出现几率,第一次出现的字符串获胜,求最终每个字符串的获胜几率
解:
dp的时候结束结点只转移到自己就行了
回文自动机/Manacher
BZOJ 3160 万径人踪灭
大意:
给定一个由′a′和′b′构成的字符串,求不连续回文子序列的个数
解:
利用补集转化思想,我们可以求出总回文子序列的个数,然后减掉连续的。
连续的可以用Manacher算法解决,不连续的可以用FFT解决
BZOJ 2084 Poi2010
大意:
给定一个长度为n的01串,问有多少个子串满足翻转并取反后和原来一样
解:
定义0=1,0≠0,1≠1跑Manacher即可
BZOJ 3676 Apio2014 回文串
大意:
定义一个回文串的出现值为出现次数*长度,求最大出现值
解:
总之这是一个回文自动机裸题
后缀自动机/后缀数组
SPOJ8222 NSUBSTR - Substrings
http://blog.csdn.net/hbhcy98/article/details/51055733
SPOJ1811 LCS - Longest Common Substring
http://blog.csdn.net/hbhcy98/article/details/51056010
SPOJ1812 LCS2 - Longest Common Substring II
http://blog.csdn.net/hbhcy98/article/details/51057065
SPOJ7258 SUBLEX - Lexicographical Substring Search
http://blog.csdn.net/hbhcy98/article/details/51058966
UOJ35 后缀排序
http://blog.csdn.net/hbhcy98/article/details/51088557
BZOJ1692 Usaco2007 Dec 队列变换
http://blog.csdn.net/hbhcy98/article/details/51089554
BZOJ3998 TJOI2015 弦论
http://blog.csdn.net/hbhcy98/article/details/51092868
BZOJ2946 Poi2000 公共串
http://blog.csdn.net/hbhcy98/article/details/51093117
BZOJ2882 工艺
http://blog.csdn.net/hbhcy98/article/details/51271987
BZOJ3238 Ahoi2013 差异
http://blog.csdn.net/hbhcy98/article/details/51273315