给定一个整数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等人的论文“ Duval生成Lyndon单词的算法的平均成本”作为证明)
该算法按字典顺序生成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”.
下面是上述方法的实现:
C++
// C++ implementation of
// the above approach
#include
using namespace std;
int main()
{
int n = 2;
char S[] = {'0', '1', '2' };
int k = 3;
sort(S, S + 3);
// To store the indices
// of the characters
vector w;
w.push_back(-1);
// Loop till w is not empty
while(w.size() > 0)
{
// Incrementing the last character
w[w.size()-1]++;
int m = w.size();
if(m == n)
{
string str;
for(int i = 0; i < w.size(); i++)
{
str += S[w[i]];
}
cout << str << endl;
}
// Repeating w to get a
// n-length string
while(w.size() < n)
{
w.push_back(w[w.size() - m]);
}
// Removing the last character
// as long it is equal to
// the largest character in S
while(w.size() > 0 && w[w.size() - 1] == k - 1)
{
w.pop_back();
}
}
return 0;
}
// This code is contributed by AdeshSingh1
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