zoukankan      html  css  js  c++  java
  • 【学习笔记】后缀数组(2)

    后缀数组学习笔记(2)


    后缀数组有多种多样的搞法,这里选讲几道。下文中,部分题目&思路来自论文。

    Luogu P4051 [JSOI2007]字符加密

    链接

    题意:给出一个字符串,假定其长度为(len),按照环的方式读出(len)个字符串,将其从小到大排序,依次输出最后一个字母,(len le 10^5)

    题解:后缀数组的直接运用。

    看到环,我们可以想到将其破环为链,得到一个长度为(len imes2)的字符串,将其用后缀数组求出所有后缀的顺序,我们就得到了长度为(len)的后缀的顺序(只按照了字符串顺序排序,如果相同,顺序是按照其所在后缀的大小排序的)。从小到大遍历(sa)数组,若(sa_i<len)(从0开始的情况下),就输出末位字母,也就是(sa_i+len-1),就得到了答案。

    单个字符串问题

    此种题目的一个常用做法是先求后缀数组和 (height) 数组,然后利用 (height)数组进行求解

    Luogu 2743 [USACO5.1]乐曲主题Musical Themes

    (POJ1743,本题数据范围缩小了点)

    题目链接 题意:给出(N)个数,求出不重叠的最长的重复子串。(若长度不足(5),输出(0)

    注意:一个子串为另一个子串加或减同一个数,这两个子串仍然相同。

    题解:先来考虑不重叠最长重复子串问题,我们可以用二分答案使之变为判定性问题。假如当前判断的长度为(k),那么对于两个后缀,假如它们中间存在一个i,且(height_i<k),答案不在这两个字符串中。

    那么,我们可以分成若干组,每组中的(height)都大于等于(k),如下图。当一组中存在两个数(i),(j),使得(sa_i+k-1<sa_j),则存在答案为(k)的不重叠的重复子串。

    回归本题,我们可以用差分的方法解决所谓的转调,然后按上面的方法做。

    由于细节较多,放上代码


    Luogu P2852 [USACO06DEC]牛奶模式Milk Patterns

    链接 题意:给出(N)个数,求出最长的可重叠的重复(x)次的子串的长度。

    题解:我们同样使用二分答案使其变为判定性问题。

    我们同样在二分后进行分组,如上图所示,设现在判定的长度为(k)。容易发现,每一组中都必然有一个长度为(k​)或更大的,共同的前缀。

    所以,如果组内后缀个数(ge x),即有满足条件的长度为(k)的前缀。二分求出其最大值即可。


    参考资料:

    [1] 罗穗骞,IOI2009 国家集训队论文《后缀数组——处理字符串的有力工具》2009.1

  • 相关阅读:
    android Fragment和FragmentActivity
    android 生成xml文件
    android:在ViewPager中使用Button
    android延迟执行
    android.os.NetworkOnMainThreadException 异常
    导入android工程没有R文件的解决办法
    20个常用的Java程序块
    Java中的==、equals、hasCode方法
    《head first java 》读书笔记
    【写给自己】2014-03-13
  • 原文地址:https://www.cnblogs.com/fmj123/p/10309177.html
Copyright © 2011-2022 走看看