Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 什么';后缀数组中排序的后缀的意义是什么?_String_Algorithm_Sorting_Data Structures_Suffix Array - Fatal编程技术网

String 什么';后缀数组中排序的后缀的意义是什么?

String 什么';后缀数组中排序的后缀的意义是什么?,string,algorithm,sorting,data-structures,suffix-array,String,Algorithm,Sorting,Data Structures,Suffix Array,我知道后缀数组本身的定义是,它是一个字符串所有后缀的排序数组。但我想了解一下这种分类操作的意义是什么?假设我们创建一个包含字符串所有后缀的数组,并选择不对其进行排序,然后继续构造LCP数组,那么在这种情况下,当我们试图解决最长回文子字符串、最长重复子字符串等常见问题时,会松脱什么呢 您希望在后缀数组中对所有后缀进行排序的主要原因有两个 首先,如果S和T是字符串,我们知道以下内容: T是S的子串当且仅当它是S的后缀的前缀时 例如,如果S是“回避”,T是“ida”,那么T是S的子字符串,因为它是后缀

我知道后缀数组本身的定义是,它是一个字符串所有后缀的排序数组。但我想了解一下这种分类操作的意义是什么?假设我们创建一个包含字符串所有后缀的数组,并选择不对其进行排序,然后继续构造LCP数组,那么在这种情况下,当我们试图解决最长回文子字符串、最长重复子字符串等常见问题时,会松脱什么呢

您希望在后缀数组中对所有后缀进行排序的主要原因有两个

首先,如果S和T是字符串,我们知道以下内容:

T是S的子串当且仅当它是S的后缀的前缀时

例如,如果S是“回避”,T是“ida”,那么T是S的子字符串,因为它是后缀“idance”的前缀。因此,需要快速查询S子字符串的应用程序可以根据搜索S后缀的前缀来重新表述

有鉴于此,如果您对搜索S的后缀的前缀感兴趣,那么将这些后缀存储在允许快速搜索的数据结构中是有意义的。如果我们将后缀放在一个数组中,保持它们的排序,那么您就可以查找各种前缀必须有效的位置。因此,将后缀数组设置为按排序顺序存储的S的所有后缀的数组,可以快速搜索后缀的前缀,从而搜索S的子字符串

至于你关于LCP数组的第二个问题——如果后缀没有排序,你能计算它们吗?如果这样做,你会损失什么你完全可以为任何数组计算它们,甚至是一个未排序的后缀数组,所以没有根本的理由不能这样做。但是,排序后缀数组的LCP数组具有一系列未排序后缀数组的LCP数组所不具备的良好属性。例如,后缀数组中的LCP数组可用于确定相应后缀树中内部节点的深度,或计算最长公共扩展等

排序后缀数组和LCP的一个非常重要的特性是,如果计算所有字符串的成对LCP信息,则可以通过在LCP数组上执行范围最小查询来计算任意字符串对上的LCP。这样做的原因是,如果对后缀进行排序,相邻字符串之间的最大重叠量将被保留。这在数组未排序的情况下不起作用(我将在最后再次提到这一点)

为了了解具体的故障位置,让我们看一下最长的重复子串问题。使用后缀数组的正常线性时间算法如下所示:

  • 为字符串T构造一个后缀数组
  • 为广义后缀数组构造LCP数组
  • 遍历后缀数组并找到LCP值最大的字符串
思考这最后一步为什么有效是很重要的。考虑任何重复两次的子串,称之为S。因为任何子串都是后缀的前缀,这意味着字符串Sα和Sβ必须是字符串T的后缀。如果将后缀数组按排序顺序存储,那么从前缀S开始的所有字符串都会在后缀数组中连续出现(你知道为什么吗?)。因此,如果S是最长的重复子字符串,那么以S开头的第一个后缀将有一个LCP,其下一个字符串的长度为| S |

现在,考虑如果不排序数组,那么会发生什么。在这种情况下,如果S是最长的重复子字符串,则字符串Sα和Sβ仍然是字符串T的后缀。但是,它们在后缀数组中不一定是连续的,因此不一定有线性时间算法来查找它们。例如,考虑字符串

abracadabra
未排序的后缀数组为

abracadabra$
bracadabra$
racadabra$
acadabra$
cadabra$
adabra$
dabra$
abra$
bra$
ra$
a$
$
在使用LCP信息进行注释后,我们得到

0 abracadabra$
0 bracadabra$
0 racadabra$
0 acadabra$
0 cadabra$
0 adabra$
0 dabra$
0 abra$
0 bra$
0 ra$
0 a$
  $
所以你可以看到这个算法找不到“abra”,因为它们不是连续的。您仍然可以通过尝试所有对来确定它是“abra”,但这对于大型字符串来说并不有效

我前面提到过,排序后缀数组中相邻字符串对的LCP信息可以用于计算排序后缀数组中任意字符串对的LCP信息。如果字符串未排序,则不是这样;在上面,您可以看到所有字符串都具有相邻的成对LCP 0,即使某些字符串确实具有非零公共前缀


希望这有帮助

我仍处于理解此数据结构的初步阶段,如果问题看起来是由于缺乏基本理解造成的,我表示歉意。如果您不对其进行排序,则无法实现包括LCP阵列在内的任何算法construction@ankitg是的,但不是有效的(在o(n^2),注意小o)否,但是,即使您心中有任何算法不需要排序顺序,并且只使用相邻邻居之间的LCP,它也不会有效。“假设我们创建一个包含字符串所有后缀的数组,并选择不对其排序,然后继续构造LCP数组”,这不是一个有效的操作过程,因为它很慢。非常感谢您的回复。我是这个数据结构的新手,所以你能告诉我应该从哪个算法开始构建后缀数组和lcp数组吗?一个时间复杂度为O(n logn)的算法将适合我,因为现在我并不寻找一个非常复杂的算法。谢谢:)@ankitG我描述了一个