用于生成长度为 n 的林登词的Python程序
给定一个整数n和一个字符数组S ,任务是生成长度为n的 Lyndon 单词,其中包含来自S的字符。
A Lyndon word is a string which is strictly less than all of its rotations in lexicographic order. For example, the string “012” is a Lyndon word as it is less than its rotations “120” and “201”, but “102” is not a Lyndon word as it is greater than its rotation “021”.
Note: “000” is not considered to be a Lyndon word as it is equal to the string obtained by rotating it.
例子:
Input: n = 2, S = {0, 1, 2}
Output: 01
02
12
Other possible strings of length 2 are “00”, “11”, “20”, “21”, and “22”. All of these are either
greater than or equal to one of their rotations.
Input: n = 1, S = {0, 1, 2}
Output: 0
1
2
方法: Jean-Pierre Duval 给出了一种生成 Lyndon 词的有效方法,该方法可用于生成长度为 n 的所有 Lyndon 词,时间与此类词的数量成正比。 (证明请参考 Berstel 等人的论文《Average cost of Duval's algorithm for generate Lyndon words》)
该算法按字典顺序生成 Lyndon 单词。如果w是一个 Lyndon 词,则通过以下步骤获得下一个词:
- 重复w以形成长度为n的字符串v ,使得v[i] = w[i mod |w|] 。
- 虽然v的最后一个字符是S排序顺序中的最后一个字符,但将其删除。
- 在 S 的排序顺序中,将v的最后一个字符替换为其后继字符。
For example, if n = 5, S = {a, b, c, d}, and w = “add” then we get v = “addad”.
Since ‘d’ is the last character in the sorted ordering of S, we remove it to get “adda”
and then replace the last ‘a’ by its successor ‘b’ to get the Lyndon word “addb”.
下面是上述方法的实现:
Python3
# Python implementation of
# the above approach
n = 2
S = ['0', '1', '2']
k = len(S)
S.sort()
# To store the indices
# of the characters
w = [-1]
# Loop till w is not empty
while w:
# Incrementing the last character
w[-1] += 1
m = len(w)
if m == n:
print(''.join(S[i] for i in w))
# Repeating w to get a
# n-length string
while len(w) < n:
w.append(w[-m])
# Removing the last character
# as long it is equal to
# the largest character in S
while w and w[-1] == k - 1:
w.pop()
01
02
12
有关详细信息,请参阅有关生成长度为 n 的 Lyndon 词的完整文章!