保存按后缀顺序排列的位置

长度为n的文本,每个字符位置都可作为一个延伸到结尾的后缀起点。后缀数组把这些起点按相应后缀的字典顺序排列,数组中的排名与原文位置因而是两个不同编号。

例如banana中,以a开头的后缀在排序后聚集,原文位置却并不连续。实现可以保留原文本和一个整数位置数组,比较时再读取相应字符,避免把长度n、n减一等全部后缀各复制一份而占用二次方空间。

参考:[1] [2]

共享前缀形成查询区间

具有某个模式前缀的后缀,在字典顺序中形成连续区域,因此可以通过有序搜索定位匹配范围,再把其中起点解释为模式在原文里的出现。后缀的排名顺序不一定也是这些出现位置从小到大的顺序。

相邻后缀的最长公共前缀长度,也能揭示文本中的重复片段。接口可以提供取某个排名对应位置、查询字符串排名或计算公共前缀等操作;只返回一个位置与枚举全部匹配,输出成本显然不同。

参考:[1] [2]

索引大小不等于构建时间

保存n个位置可以是线性空间,但把它们排好还需要算法。简单比较排序会在比较后缀时读取公共前缀,长重复内容可能增加字符检查;Princeton另提供三向基数快速排序版本,并明确提示极端重复输入仍可能很差。

文本改变后,原有起点及其排序也可能失效,不能把静态索引不经维护用于新文本。选择后缀数组还是逐模式扫描,应把构建成本、查询数量、字符比较和保留的辅助信息一起计算,而不是只看到一次二分定位的步骤。

参考:[1] [2]