如何在不使用矩阵的情况下对字符串旋转进行排序

时间:2011-06-21 05:07:26

标签: algorithm string sorting

我想对字符串的旋转进行排序 例如:

对于S = 'abaeb',轮播可以是'baeba'

我需要获取S的索引列表,按字典顺序排序 在我们的示例中:V = 02413

答案必须排除琐碎的矩阵行排序。

3 个答案:

答案 0 :(得分:5)

编辑:Justin Peel指出后

只需将字符串附加到自身bbaeb变为bbaebbbaeb(对于涉及字符串旋转的问题,这是一个方便的技巧)。
查找后缀数组。
遍历它并仅选择小于orignal string(5)长度的值。 上面字符串的后缀数组

aeb  7
aebbbaeb  2
b  9
baeb  6
baebbbaeb 1
bbaeb 5
bbaebbbaeb 0
eb  8
ebbbaeb  3

S = 7 2 7 6 1 5 0 4 8 3

现在追溯到Ans = 2 1 0 4 3

编辑

您可以使用Suffix array以O(n)时间复杂度解决此问题。基本上字符串的后缀数组包含按字典顺序排列的字符串的所有后缀的索引 对于字符串abaeb,字典顺序中的后缀为:

abaeb (0)
aeb   (2)
b     (4) 
baeb  (1)
e     (3)

所以后缀数组S=02413

具有O(n log ^ 2n)时间复杂度的代码在该链接处给出,具有详细说明,并且下一页具有针对O(n)的优化。 如果您想保持代码简单,那么使用已经回答的比较运算符是关键。如果您的主要关注点是效率,那么使用o(n)后缀数组构造。

答案 1 :(得分:1)

如果我理解正确,你有一个输入字符串,你正在考虑所有轮换。例如,N长度串的N个旋转将是,例如:

rotations("abcd") -> ["abcd"*, "dabc", "cdab", "bcda"]

您希望编写一个比较器函数compare(rotation1, rotation2),它将说明rotation1是否为< rotation2。或者>或== abcd,在上下文中*原始轮换为key(rotation),或者,具有与上述比较器函数等效的函数original = 'abcd' letterPositions = defaultdict(set) for i,letter in enumerate(original): letterPositions[letter].add(i) def numIndicesRotated(rotated): possibilities = set(range(len(original))) for i,letter in enumerate(rotated): possibilities &= {(j-i)%len(original) for j in letterPositions[letter]} if len(possibilities)==1: #optimization break #optimization if len(possibilities)==1: return possibilities.pop() else: raise Exception('not a rotation')

如果这不正确,请澄清问题。 =)如果正确,你的答案如下:

abcabc

请注意,如果您的字符串本身具有旋转,则旋转可能无法完全无法解析,例如: sorted(myRotations, key=numIndicesRotated)

然后你可以做{{1}}

之类的事情

答案 2 :(得分:1)

通常,对于排序,您不需要将所有已排序的项目并行保存在内存中,您只需要能够比较它们中的任何一对。

我的意思是,您可以对字符串旋转开始的索引进行排序(即1 ='baeba'等),并提供一种比较方法,该方法将根据该索引比较旋转。

虽然复杂性并不比nLog(n)好,但代码应该非常简单。此外,记忆肤色接近你能得到的最好的。以某种方式利用已排序项不是随机的知识,可能会给你更好的复杂性(但我目前不知道如何去做)。