📜  雷卡曼的顺序(1)

📅  最后修改于: 2023-12-03 15:12:50.312000             🧑  作者: Mango

雷卡曼的顺序

概述

雷卡曼的顺序(Lehmer's Order)是音乐节奏感知领域的一种算法,由数学家Derrick Henry Lehmer在1933年提出,用于计算音乐节奏的周期性。它通过求解某个音乐节奏序列的最小表示(即找到它们的最小循环移位)来判断它是否存在周期性。在计算机科学中,我们也可以使用这种算法来解决字符串循环移位问题。

算法思路

给定一个字符串S,它的所有循环移位可以表示为S[i:n]+S[0:i](其中nS的长度,i0~n-1的整数),我们需要找到其最小表示。Lehmer的顺序算法通过比较S[i:n]+S[0:i]S[j:n]+S[0:j]的大小来找到最小表示,其中ij0~n-1的整数,且保证i!=j。具体地:

对于每个位置i(0<=i<n),计算出所有位于闭区间[i+1,n-1]和开区间(0,i)的位置j,使得相应的S[j:n]+S[0:j]S的一个后缀,然后比较所有这样的后缀。具体来说,我们维护一个最小后缀smin和它对应的位置imin,遍历所有位置i时,比较后缀S[i:n]+S[0:i]smin。如果它比smin小,就更新sminimin

最终结果就是S[imin:n]+S[0:imin]

代码实现
def lehmer_order(s):
    n = len(s)
    i, j, k = 0, 1, 0
    while i < n and j < n and k < n:
        if s[(i+k)%n] == s[(j+k)%n]:
            k += 1
        elif s[(i+k)%n] > s[(j+k)%n]:
            i += k+1
            if i <= j:
                i = j + 1
            k = 0
        else:
            j += k+1
            if j <= i:
                j = i+1
            k = 0
    return min(i, j)

def min_cyclic_shift(s):
    n = len(s)
    i = lehmer_order(s)
    return s[i:n]+s[0:i]
时间复杂度

Lehmer的顺序算法时间复杂度为$O(n\log n)$,其中$n$是字符串s的长度。