def suffix_array(s):
n = len(s)
sa = list(range(n))
g = [ord(x) for x in s] + [0] * n
d = 1
while True:
sa.sort(key=lambda i: (g[i], g[i + d]))
t = [0] * (n + n)
t[sa[0]] = 1
for prev, cur in itertools.pairwise(sa):
t[cur] = t[prev] + (g[cur] > g[prev] or g[cur + d] > g[prev + d])
if t[sa[-1]] == n:
break
g = t
d *= 2
return sa