字符串练习题
https://vjudge.net/contest/278181
写在前面:
1)一个子串既是一个后缀的前缀,又是一个前缀的后缀
2)AC自动机/后缀数组后常接DP/数据结构
Problem 0 Long Long Message (后缀数组)
http://poj.org/problem?id=2774
思路:
两个字符串拼起来,求后缀数组和height数组
记录一下该后缀是从第一个字符串开始的还是第二个字符串开始的
对于从不同字符串开始的相邻位置的后缀 ans=max(height)(height表示的两个相邻后缀的起始位置为不同字符串才对答案有贡献)
为了避免从第一个字符串开始的后缀延伸到第二个字符串,造成结果可能会大,我们可以算各项结果时与在第一个字符串内长度取min,或者在两个字符串接起来的时候在中间加一个不可能被匹配的其他字符
Problem1 [BJWC2011]禁忌 (AC自动机)
https://www.lydsy.com/JudgeOnline/problem.php?id=2553
https://www.luogu.org/problemnew/show/P4569
思路:f[i][j]表示已把前i位填好,走到AC自动机上j这个节点所有方案价值总和
枚举第i+1个位置填哪个字符
f[i][j]-> f[i+1][trans[j][k]]
-> f[i+1][rt] (增加价值)
一个节点的fail指针指向的位置被打上标记,这个节点也要打上标记(因为是包含关系)
矩阵优化
Problem 2
https://www.lydsy.com/JudgeOnline/problem.php?id=1014
思路:因为有插入和删除,所以用平衡树维护区间的hash值
f[i]=s[p1,p1+i]=?=s[p2,p2+i] 先1后0的一段 二分长度,得到hash值比较一下
Problem 3
https://www.lydsy.com/JudgeOnline/problem.php?id=1030
f[i][j]表示前i位填好了,j表示走到了AC自动机上j这个点,k0/1表示有没有出现过单词
Problem 4 [HEOI2012]旅行问题 (AC自动机)
https://www.lydsy.com/JudgeOnline/problem.php?id=2746
https://www.luogu.org/problemnew/show/P4600
思路:由fail指针定义,建立fail树,求两个前缀所在节点的lca
Problem 6 [NOI2011]阿狸的打字机 (AC自动机)
Problem 7
思路:扩展KMP,找到一个后缀能匹配到末尾,则它前面的串能循环匹配到末尾
Problem 11
去重:一个子串是一个后缀的前缀
将后缀排序,每个后缀贡献的子串个数=改后缀长度-height,易证会按字典序贡献子串,二分答案即可
不去重:
先考虑一次的做法:基于去重的算法,每次二分到一个位置,求出rank比它大的那些后缀中字典序<=它的前缀个数,易知为它们的公共前缀个数,即从i位置到j位置的min height ,从该位置往后扫一遍即可。
若做k次:用线段树、单调栈之类的东西搞一搞,预处理出每个位置到最后位置的sigma min height
Problem 13
枚举答案的长度l,将字符串分段,假设第4段与第5段不一样,二分找到第5段该删的点,删了之后拼起来
特判:若第一段和第二段不一样,把第三段搞出来看看
hash
复杂度:n/1+n/2+n/3+……n/n≈nlogn
[AHOI2013]差异
https://www.lydsy.com/JudgeOnline/problem.php?id=3238
https://www.luogu.org/problemnew/show/P4248
前两项很好搞,主要搞第三项
找到其中最小的height值,画一条线,若i,j一个在上一个在下,则值即为改height值,个数为上面的数量*下面的数量
若i,j都在上或都在下,递归依次看上面、下面
st表???