Open In App

Generating Lyndon words of length n

Last Updated : 09 Sep, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Given an integer n and an array of characters S, the task is to generate Lyndon words of length n having characters from 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.

Examples:

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

Approach: 

There exists an efficient approach to generate Lyndon words which was given by Jean-Pierre Duval, which can be used to generate all the Lyndon words upto length n in time proportional to the number of such words. (Please refer to the paper “Average cost of Duval’s algorithm for generating Lyndon words” by Berstel et al. for the proof) The algorithm generates the Lyndon words in lexicographic order. 

If w is a Lyndon word, the next word is obtained by the following steps:

  1. Repeat w to form a string v of length n, such that v[i] = w[i mod |w|].
  2. While the last character of v is the last one in the sorted ordering of S, remove it.
  3. Replace the last character of v by its successor in the sorted ordering of S.

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”.

Below is the implementation of the above approach: 

C++




// C++ implementation of
// the above approach
#include<bits/stdc++.h>
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<int> 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


Java




// Java program to check if a string is two time
// rotation of another string.
import java.util.*;
public class Main
{
 
  // Driver method
  public static void main(String[] args)
  {
    int n=2;
    char S[]={'0', '1', '2' };
    int k = 3;
    Arrays.sort(S);
 
    // To store the indices
    // of the characters
    ArrayList<Integer> w = new ArrayList<Integer>();
    w.add(-1);
    // Loop till w is not empty    
    while(w.size() > 0)
    {
 
      // Incrementing the last character
      Integer value = w.get(w.size()-1); // get value
      value = value + 1; // increment value
      w.set(w.size()-1, value); // replace value
      int m = w.size();
      if(m == n)
      {
        String str="";
        for(int i = 0; i < w.size(); i++)
        {
          value = w.get(i);
          str += S[value];
        }
        System.out.println(str);
      }
 
      // Repeating w to get a
      // n-length string
      while(w.size() < n)
      {
        value = w.size() - m;
        value = w.get(value);
        w.add(value);
      }
 
      // Removing the last character
      // as long it is equal to
      // the largest character in S
      while(w.size() > 0 && w.get(w.size() - 1) == k - 1)
      {
        w.remove(w.size()-1);
      }
    }
  }
}
 
// This code is contributed by Aarti_Rathi


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()


C#




using System;
using System.Collections.Generic;
 
class GFG
{
   
  // Driver code
  public static void Main ()
  {
    int n=2;
    char [] S={'0', '1', '2' };
    int k = 3;
    Array.Sort(S);
 
    // To store the indices
    // of the characters
    List<int> w = new List<int>();
    w.Add(-1);
    // Loop till w is not empty    
    while(w.Count > 0)
    {
 
      // Incrementing the last character
      w[w.Count-1]++;
      int m = w.Count;
      if(m == n)
      {
        string str="";
        for(int i = 0; i < w.Count; i++)
        {
          str += S[w[i]];
        }
        Console.WriteLine(str);
      }
 
      // Repeating w to get a
      // n-length string
      while(w.Count < n)
      {
        w.Add(w[w.Count - m]);
      }
 
      // Removing the last character
      // as long it is equal to
      // the largest character in S
      while(w.Count > 0 && w[w.Count - 1] == k - 1)
      {
        w.RemoveAt(w.Count-1);
      }
    }
  }
}
 
// This code is contributed by Aarti_Rathi


Javascript




<script>
 
// JavaScript implementation of
// the above approach
 
// driver code
 
let n = 2;
let S = ['0', '1', '2'];
let k = 3;
S.sort();
 
// To store the indices
// of the characters
let w = [];
w.push(-1);
 
// Loop till w is not empty
while(w.length > 0)
{
 
    // Incrementing the last character
        w[w.length-1]++;
        let m = w.length;
        if(m == n)
        {
            let str = "";
            for(let i = 0; i < w.length; i++)
            {
                str += S[w[i]];
            }
            document.write(str,"</br>");
        }
     
        // Repeating w to get a
        // n-length string
        while(w.length < n)
        {
            w.push(w[w.length - m]);
        }
     
        // Removing the last character
        // as long it is equal to
        // the largest character in S
        while(w.length > 0 && w[w.length - 1] == k - 1)
        {
            w.pop();
        }
}
 
// This code is contributed by shinjanpatra
 
</script>


Output

01
02
12


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads