我想旋转一个字符串并打印出那些旋转中最大的字典缩写?

时间:2016-01-20 04:59:20

标签: string rotation lexicographic

s = raw_input()
n = len(s)
el = []
z = n - 1
while z >= 0:
    x = s[z:] + s[:z]
    z = z - 1
    el.append(x)
print max(el)

代码工作正常但效率很低。是否有更有效的方法来解决问题?

1 个答案:

答案 0 :(得分:0)

方法

您可以使用suffix arrays在线性时间内解决此问题。给定输入字符串s,构造加倍的字符串ss。使用线性时间算法构造ss的后缀数组。后缀数组按字典顺序保存ss的充分索引。最后,向后扫描后缀数组,跳过ss下半部分的索引。从ss的上半部开始的按字典顺序排列的最大后缀可以被修整为s的旋转度。

该问题与here中描述的问题类似,不同之处在于该问题与按字典顺序的最小旋转有关,并且您希望按字典顺序的最大旋转。

实施

上面链接的文章提到了一些可用于后缀数组构造的算法。在这里,我不会对此部分进行明确的解释,但是对于Python实现,请参见此article

因此,假设您已对后缀数组算法create_suffix_array(s: str) -> [int]进行了某种实现,以使create_suffix_array(s)以字典顺序返回足够的索引序列,则可以将该算法应用于您的问题,如下所示:

def rotate(s: str, n: int) -> str:
  return s[n:] + s[:n]

def solve(s: str) -> str:
  indices: [int] = create_suffix_array(s + s)

  is_first_half = lambda i: i < len(s)

  best_index = next(filter(is_first_half, reversed(indices)))

  return rotate(s, best_index)

算法的正确性

s为长度为n的字符串。令iss的字典上最大后缀的索引,该后缀始于ss的上半部分。 ss定义的i后缀为s[i,n-1]s

考虑j中的任何[0,n-1]。然后,由ss定义的j后缀不能大于s[i,n-1]ss[j,n-1]s <= s[i,n-1]s这样。然后得出结论,这些充分的任意两个相等大小的前缀具有相同的顺序。特别是s[j,n-1]s[0,j-1] <= s[i,n-1]s[0,i-1],因为两者都是两个n大小的前缀。

因此,s[i,n-1]s[0,i-1]s在字典上最大的旋转。