【问题标题】:find the lexicographically minimal string rotation without suffix tree and in O(n) [duplicate]找到没有后缀树和 O(n) 的字典上最小的字符串旋转 [重复]
【发布时间】:2013-08-10 21:55:09
【问题描述】:

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

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

【问题讨论】:

  • 你可以很容易地找到它:生成所有可能的字符串(其中会有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) 时间。

标签: string algorithm complexity-theory circular-buffer


【解决方案1】:

理论 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]

【讨论】:

    【解决方案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
    

    这应该会给你一个 O(n) 的预期复杂度。

    【讨论】:

    • 我认为你的解决方案对于像 ABABABABABABABABABABAD 这样的情况会失败(在这种情况下,解决方案将是 O(n^2))
    猜你喜欢
    • 1970-01-01
    • 2013-02-06
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 2013-09-08
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多