在通过输入数组进行单次迭代时:
设置一个数组smallest[n]
,其中smallest[i]
表示长度增加的子字符串i
可以以结尾的最小元素(例如,如果smallest[3] = 5
,这意味着有一个长度为3的子字符串以a结尾5
,并且没有长度为3的子字符串以a结尾4
,否则smallest[3]
将是4
)。
i
到目前为止,我们可以跟踪最长的子字符串,smallest[i]
如果该元素大于当前元素,则只需替换。
关于这个数组的一个重要说明:这个数组中的元素将严格按递增顺序排列,也就是说,如果数组中存在长度i
以 element 结尾的子字符串x
,则不再有包含等于或小于元素的子字符串x
(这是因为较长的子字符串将包含一个长度i
以小于 的元素结尾的子字符串x
,因此smallest[i]
将是该元素而不是x
)。
除了这个数组之外,还要保留一个二叉搜索树 (BST),它将元素映射到子字符串长度(本质上与数组相反)。
更新时smallest
,还要从 BST 中删除旧元素并插入新元素。
(到目前为止,所有这些都是关于原始数组 A 中的子字符串,而不是删除后的数组 C)
使用它,我们可以longestSSAfterB
通过查找 BST 中小于该元素的最大元素并将该长度加 1 来找到 C 中以任何元素结尾的最长子字符串(直接跟在某个 B 之后)。
C 中以任何给定元素结尾的最长子字符串将只是 1 + 以前一个元素结尾的最长子字符串的最大值(如果它更小,则为 0)和longestSSAfterB
.
C 中最长的子串就是我们在上面找到的最长子串。
这一切都需要O(n log n)
。
例子:
A = [3 2 5 7 1 2 8 1]
BST.floor(i)+1
currentSS longestSSAfterB longestSSinC smallest BST
A[0]=3 1 0+1=1 max(1,0+1)=1 [3] [(3→1)]
A[1]=2 1 0+1=1 max(1,0+1)=1 [2] [(2→1)]
A[2]=5 2 (2→1)->1+1=2 max(2,1+1)=2 [2,5] [(2→1), (5→2)]
A[3]=7 3 (5→2)->2+1=3 max(3,2+1)=2 [2,5,7] [(2→1), (5→2), (7→3)]
A[4]=1 1 0+1=1 max(1,0+1)=1 [1,5,7] [(1→1), (5→2), (7→3)]
A[5]=2 2 (1→1)->1+1=2 max(2,1+1)=2 [1,2,7] [(1→1), (2→2), (7→3)]
A[6]=8 3 (7→3)->3+1=4 max(4,2+1)=4 [1,2,7] [(1→1), (2→2), (7→3)]
A[7]=1 1 0+1=1 max(1,0+1)=1 [1,5,7] [(1→1), (5→2), (7→3)]
Longest substring = max(longestSSinC) = 4