通过后缀数组的最长公共子字符串:sentinel

时间:2019-08-29 11:04:21

标签: algorithm suffix-array longest-substring

我正在阅读一系列字符串中最长的常见子字符串的(显然)众所周知的问题,并且一直在关注这两个视频,它们讨论了如何使用后缀数组解决问题:(请注意,这个问题并不不需要您观看):

https://youtu.be/Ic80xQFWevc

https://youtu.be/DTLjHSToxmo

第一步是首先将所有源字符串连接成一个大字符串,并用一个“唯一的”标记来分隔每个源,其中每个标记的ASCII码都小于任何字符串中可能出现的任何字符的ASCII码。 。这样我们就可以拥有单独的字符串

abca
bcad
daca

并连接它们以给出

abca#bcad$daca%

现在,可能的哨兵数量有限,如果我们有大量的琴弦,则会导致问题。确实,有人在第一个链接的视频中指出了这一点,对此的回应是

  

正确,解决方案是将您的字母映射到自然数   并根据您需要的哨兵数量向上移动。这使您能够   在值[1,N]和您的字母之间总是有前哨   在那之上。此技巧使后缀数组可伸缩,但是您需要   撤消移位,解码存储在后缀中的真实值   数组。

我不明白答案的含义。

我知道我可以在视频中发布我的问题,但是我不能保证(及时)回复,而且这里的观众范围更广,所以我在这里问人:有人可以解释一下吗这个答案意味着以及如何实现?

1 个答案:

答案 0 :(得分:1)

不知道如何比引用的注释更好/不同地解释它。也许一个例子会有所帮助。请注意,我这里不是使用真正的ASCII代码,因为我不想显示约100个源字符串的示例。因此,我们假设A = 1,B = 2,C = 3,等等。

因此,您的源字符串abca bcad daca将转换为[1,2,3,1],[2,3,1,4],[4,1,3,1],但是为了适合三个标记,您必须将所有这些值上移3,即现在1到3已成为标记和A = 4,B = 5,等等。连接的“字符串”(实际上是现在的整数列表)为[4,5,6,4, 1, 5,6,4,7, 2, 7,4,6,4, 3]。然后,您可以将其转换回字符defda...,进行算法处理,然后再转换回,以消除偏移。

但是,我要说的是,除了移位整数,我们还可以对标记使用负数,然后直接在整数列表上工作,而不是将其转换回字符(对于负数是不可能的) ):[1,2,3,1, -1, 2,3,1,4, -2, 4,1,3,1, -3](注意:我不是观看了视频,并且不知道该特定算法的工作原理;可能是负数是一个问题,例如,如果使用了一些一种“最短路径”算法。)