String 在O(n)中查找不带后缀树的字典最小字符串旋转

String 在O(n)中查找不带后缀树的字典最小字符串旋转,string,algorithm,complexity-theory,circular-buffer,String,Algorithm,Complexity Theory,Circular Buffer,如何在循环数组中查找索引,以便从该索引开始形成的字符串按字典顺序排在第一位 例如:在循环数组ABCDEABCDE中 答案是6,因为从第6位的元素A开始的循环字符串在由循环数组的所有可能字符串组成的字典中排在第一位。理论A:如果字母X在长度N的序列中出现K次,X至少出现两次,使得它们之间的距离小于N/K 查找最小字母,并在排序列表中排列指向其所有匹配项的指针。叫它A 对于给定的r,在a[i]+r处查找字母的min,并过滤掉a[i]+r处的元素不等于min的所有指针。同时过滤掉a[j]处的所有指针,

如何在循环数组中查找索引,以便从该索引开始形成的字符串按字典顺序排在第一位

例如:在循环数组ABCDEABCDE中
答案是6,因为从第6位的元素A开始的循环字符串在由循环数组的所有可能字符串组成的字典中排在第一位。

理论A:如果字母X在长度N的序列中出现K次,X至少出现两次,使得它们之间的距离小于N/K

查找最小字母,并在排序列表中排列指向其所有匹配项的指针。叫它A

对于给定的r,在a[i]+r处查找字母的min,并过滤掉a[i]+r处的元素不等于min的所有指针。同时过滤掉a[j]处的所有指针,使a[j]=a[i]+r用于某些i

您必须最多运行N/K次以上语句,每次运行最多花费O(K)次。因此,该算法的复杂度为O(N)

更详细的算法: 假设Z是我们正在处理的循环列表

def filter(A,Z,r):
    t = min( Z[A[i]+r] ) forall i
    remove A[i] if Z[A[i]+r]!=t forall i

    rmflag = [false if A[i]==A[j]+r else false for i in range(len(A)] //NOTE: This step can be done in O(len(A)) time since A is sorted
    remove A[i] if rmflag[i]

这应该会给您一个O(n)预期的复杂性

您可以很容易地找到它:生成所有可能的字符串(其中将有
n
,其中
n
是原始字符串的长度),然后使用线性搜索/选择简单地找到第一个字符串。这两个操作都需要
O(n)
时间。@H2CO3:复杂性将非常大。我正在寻找O(n)算法。你的方法是O(n^2)。@jairaj“非常大”?为什么会这样?需要
O(n)
生成子字符串,然后
O(n)
搜索最小值。(无论如何,yoyu现在是在寻找一个
O(n)
还是
O(1)
解决方案?你的评论与标题中的标准不符。)@H2CO3如果你不小心的话,需要
O(n)
生成一个长度
n
的子字符串,然后
O(n^2)
才能生成它们。@H2CO3:你到底是如何使用的“线性搜索/选择”以查找字典最小字符串?除非您使用特殊技巧,否则您需要至少进行n-1次比较(想想锦标赛选择),每一次比较都可能需要O(n)时间。我认为您的解决方案在ababad这样的情况下失败(在这种情况下,解决方案将是O(n^2))
Step 1: find the min char, call it minChar
Step 2: build list L0 = {i: string[i] == minChar, but string[i-1] != minChar}
Step 3: if L0.size() == 1, return L0[0]
step 3:
        3.0 set k=0, let L = L0
        3.1 k++
        3.2 BUild L1 = {i+1, i in L}. Build L = {i: string[i] is smallest for any k in L1}
        3.3 If L.size() == 1, return L[0]-k. Otherwise goto 3.1 to repeat