ACM的第六乐章--后缀数组
以下题目属于入门级别
hdu 1403 ural 1517 简单后缀数组应用
http://acm.hdu.edu.cn/showproblem.php?pid=1403
http://acm.timus.ru/problem.aspx?space=1&num=1517
http://poj.org/problem?id=2774
题意:给两串字符,求最长的公共子串。
思路:把两个串合成一个串,之间用‘#’隔开,然后对后缀排序,求出height数组值后,当height[k]为两个串的公共前缀长度时,取最大的。
hdu 3518
http://acm.hdu.edu.cn/showproblem.php?pid=3518
重复至少俩次的不重叠子串的个数
我还是觉得大牛的这句解释十分重要,还是没彻底理解透
若在假设重复子串的长度最多为L的限制下有解, 则对于任意一个比L小的限制L'<L, 也一定有解. 这就说明存在解的连续性
给出一个关于LCP的定理LCP(SA[i], SA[j]) = RMQ(Height[i+1..j]). 由此, 若存在k, 满足Height[k] < L, 则对于所有i, j 满足i < k < j, 有LCP(SA[i], SA[j]) < L. 即公共长度至少为L的两个后缀, 不会跨过一个小于L的Height低谷k, 所以我们可以得到一些由这些低谷划分开的连续的段.
枚举字串长度h
对于每一次的h,利用height数组,找出连续的height大于等于h的里面最左端和最右端得为之l和r。
如果l + h - 1 < r的话,说明没有重叠,答案加1.
1711 Number Sequence
http://acm.hdu.edu.cn/showproblem.php?pid=1711
题意:给两个数字序列,判断第一个是否包含了第二个数列。
思路一(正解): 直接kmp;
思路二(YY): 求出第一个序列的前缀和,在第一个序列中取和第二个序列等长的子序列,如果这个子序列的和与第二个序列的和一样,才进行匹配算法。这个算法可以过不了一些特殊的数据。但在很短的时间内过了。
思路三:后缀数组直接应用。
xmu 1337 后缀数组 + 暴力匹配
http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1337
题意:在一个串中求出一个长度为n的、重复了m次的子串(不能重叠)。
思路:一直以为正解是后缀数组加其它高效的搜索方法。一水才知道,就是纯后缀数组+暴力匹配。
先用后缀数组求出 sa,height两个数组的值,当height[i]=n时,取出当前子串,进行暴力匹配。囧~~~
hdu 2328 Corporate Identity
http://acm.hdu.edu.cn/showproblem.php?pid=2328
题意:求多个字符串的最长公共子串,若有多个输出字典序最小。
思路:先进行后缀数组操作。然后二分子串长度,根据height和sa数组的值,判断当前长度是否合适。
当然,这里面还有hash映射的。
xt 2011市赛:Forbidden Words
http://openoj.awaysoft.com/JudgeOnline/problem.php?id=1897
思路:利用后缀数组将,FW的首尾位置标记出来,然后进行线性扫描,求解最长的子串。
不过,不知道为什么,有五组数据就是过不了,求解中~~~
poj 3581 Sequence
http://poj.org/problem?id=3581
题意:给一个整数序列,要求划分成三个连续的子序列,同时将子序列反序,使得最后得到的序列的子典序最小。
思路:对于这个序列,很明显,每个整数最后都要反序一次,所以可以先把原来的序列反序,这样问题就可以转化成在一个序列里,划分三个连续的子序列,按一定的顺序输出这个子序列,使得最后的序列字典序最小。先考虑第一个序列,因为原序列的第一个整数是最大的,也就是反序列中最后一个元素是最大的,所以第一个序列就是反序列后的最小后缀。求第二个序列的时候因为没有了第一个序列的最大元素,所以不能直接求最小后缀。这时可以先把第一个序列割出来,然后重复一次剩下的序列,再求一次最小后缀就是第二个序列了。
PS:这个题的输入文件中有多余的输入~~~
最长回文 hdu 3068 poj 3974 ural 1297
http://acm.hdu.edu.cn/showproblem.php?pid=3068
http://poj.org/problem?id=3974
http://acm.timus.ru/problem.aspx?space=1&num=1297
题意:给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
思路:
1、Manacher解法,再每个字母前后面插入字符'#',再找最长回文串。
2、拓展KMP解法
3、后缀数组解法(超时了)
4、二分+暴力(水过)
解法4:(三个题目都可以这样解)明显,如果回文的长度是L,那么答案一定不小于L,因而能够二分答案。在判断L是否满足的时候,可以这样做:
sum[a]是前a个字符串和;
如果L是偶数,且sum[a]-sum[a-L/2]=sum[L/2+a] - sum[a],则开始进行回文匹配。
如果L是奇数,且sum[a-1]-sum[a-L/2-1]=sum[L/2+a]-sum[a];则开始进行回文匹配。
二分的时候先进行奇性匹配,因为L+1>L;如果成功则返回。
poj 3261 Milk Patterns
http://poj.org/problem?id=3261
题意:求一个整数序列最长的重复k次的序列,序列可以重叠。
思路:后缀数组+二分:得到height数组后,二分答案ans,检查height数据里是否有连续的k-1个值不小于ans。
poj 3623 Best Cow Line, Gold
http://poj.org/problem?id=3623
题意:给一个字符序列,要求不断的从原序列的首或尾取一个字符,重新生成一个字符序列使得字典序最小。
思路:一开始以为直接贪心,比较首尾的字符大小就可以了,深入想就知道,当首尾一样的时候,要依靠后一位作判断。因此问题就转成两个字符串的大小比较(首为顺序,尾为反序)。这样先把原字符串反序放到原字符串的后面,对整个串进行后缀排序,最后就可以rank数组贪心答案。