Skip to content
Related Articles

Related Articles

Improve Article

De Bruijn sequence | Set 1

  • Difficulty Level : Expert
  • Last Updated : 10 Jul, 2021

Given an integer n and a set of characters A of size k, find a string S such that every possible string on A of length n appears exactly once as a substring in S. Such a string is called de Bruijn sequence.

Examples: 

Input: n = 3, k = 2, A = {0, 1) 
Output: 0011101000 
All possible strings of length three (000, 001, 010, 011, 100, 101, 110 and 111) appear exactly once as sub-strings in A.

Input: n = 2, k = 2, A = {0, 1) 
Output: 01100 
 

Approach: 
We can solve this problem by constructing a directed graph with kn-1 nodes with each node having k outgoing edges. Each node corresponds to a string of size n-1. Every edge corresponds to one of the k characters in A and adds that character to the starting string. 



For example, if n=3 and k=2, then we construct the following graph:
 

  • The node ’01’ is connected to node ’11’ through edge ‘1’, as adding ‘1’ to ’01’ (and removing the first character) gives us ’11’.
  • We can observe that every node in this graph has equal in-degree and out-degree, which means that a Eulerian circuit exists in this graph.
  • The Eulerian circuit will correspond to a de Bruijn sequence as every combination of a node and an outgoing edge represents a unique string of length n.
  • The de Bruijn sequence will contain the characters of the starting node and the characters of all the edges in the order they are traversed in.
  • Therefore the length of the string will be kn+n-1. We will use Hierholzer’s Algorithm to find the Eulerian circuit. The time complexity of this approach is O(kn).

Below is the implementation of the above approach:  

C++




// C++ implementation of
// the above approach
#include <bits/stdc++.h>
using namespace std;
 
unordered_set<string> seen;
vector<int> edges;
 
// Modified DFS in which no edge
// is traversed twice
void dfs(string node, int& k, string& A)
{
    for (int i = 0; i < k; ++i) {
        string str = node + A[i];
        if (seen.find(str) == seen.end()) {
            seen.insert(str);
            dfs(str.substr(1), k, A);
            edges.push_back(i);
        }
    }
}
 
// Function to find a de Bruijn sequence
// of order n on k characters
string deBruijn(int n, int k, string A)
{
 
    // Clearing global variables
    seen.clear();
    edges.clear();
 
    string startingNode = string(n - 1, A[0]);
    dfs(startingNode, k, A);
 
    string S;
 
    // Number of edges
    int l = pow(k, n);
    for (int i = 0; i < l; ++i)
        S += A[edges[i]];
    S += startingNode;
 
    return S;
}
 
// Driver code
int main()
{
    int n = 3, k = 2;
    string A = "01";
 
    cout << deBruijn(n, k, A);
 
    return 0;
}

Java




// Java implementation of
// the above approach
import java.util.*;
 
class GFG
{
 
    static Set<String> seen = new HashSet<String>();
    static Vector<Integer> edges = new Vector<Integer>();
 
    // Modified DFS in which no edge
    // is traversed twice
    static void dfs(String node, int k, String A)
    {
        for (int i = 0; i < k; ++i)
        {
            String str = node + A.charAt(i);
            if (!seen.contains(str))
            {
                seen.add(str);
                dfs(str.substring(1), k, A);
                edges.add(i);
            }
        }
    }
 
    // Function to find a de Bruijn sequence
    // of order n on k characters
    static String deBruijn(int n, int k, String A)
    {
 
        // Clearing global variables
        seen.clear();
        edges.clear();
 
        String startingNode = string(n - 1, A.charAt(0));
        dfs(startingNode, k, A);
 
        String S = "";
 
        // Number of edges
        int l = (int) Math.pow(k, n);
        for (int i = 0; i < l; ++i)
            S += A.charAt(edges.get(i));
        S += startingNode;
 
        return S;
    }
 
    private static String string(int n, char charAt)
    {
        String str = "";
        for (int i = 0; i < n; i++)
            str += charAt;
        return str;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int n = 3, k = 2;
        String A = "01";
 
        System.out.print(deBruijn(n, k, A));
    }
}
 
// This code is contributed by 29AjayKumar

Python3




# Python3 implementation of
# the above approach
import math
 
seen = set()
edges = []
 
# Modified DFS in which no edge
# is traversed twice
def dfs( node, k, A):
     
    for i in range(k):
        str = node + A[i]
        if (str not in seen):
            seen.add(str)
            dfs(str[1:], k, A)
            edges.append(i)
 
# Function to find a de Bruijn sequence
# of order n on k characters
def deBruijn(n, k, A):
     
    # Clearing global variables
    seen.clear()
    edges.clear()
     
    startingNode = A[0] * (n - 1)
    dfs(startingNode, k, A)
     
    S = ""
     
    # Number of edges
    l = int(math.pow(k, n))
    for i in range(l):
        S += A[edges[i]]
         
    S += startingNode
    return S
 
# Driver code
n = 3
k = 2
A = "01"
 
print(deBruijn(n, k, A))
 
# This code is contributed by shubhamsingh10

C#




// C# implementation of
// the above approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
    static HashSet<String> seen = new HashSet<String>();
    static List<int> edges = new List<int>();
 
    // Modified DFS in which no edge
    // is traversed twice
    static void dfs(String node, int k, String A)
    {
        for (int i = 0; i < k; ++i)
        {
            String str = node + A[i];
            if (!seen.Contains(str))
            {
                seen.Add(str);
                dfs(str.Substring(1), k, A);
                edges.Add(i);
            }
        }
    }
 
    // Function to find a de Bruijn sequence
    // of order n on k characters
    static String deBruijn(int n, int k, String A)
    {
 
        // Clearing global variables
        seen.Clear();
        edges.Clear();
 
        String startingNode = strings(n - 1, A[0]);
        dfs(startingNode, k, A);
 
        String S = "";
 
        // Number of edges
        int l = (int) Math.Pow(k, n);
        for (int i = 0; i < l; ++i)
            S += A[edges[i]];
        S += startingNode;
 
        return S;
    }
 
    private static String strings(int n, char charAt)
    {
        String str = "";
        for (int i = 0; i < n; i++)
            str += charAt;
        return str;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        int n = 3, k = 2;
        String A = "01";
 
        Console.Write(deBruijn(n, k, A));
    }
}
 
// This code is contributed by 29AjayKumar

Javascript




<script>
 
// Javascript implementation of
// the above approach
var seen = new Set();
var edges = [];
 
// Modified DFS in which no edge
// is traversed twice
function dfs(node, k, A)
{
    for (var i = 0; i < k; ++i)
    {
        var str = node + A[i];
        if (!seen.has(str))
        {
            seen.add(str);
            dfs(str.substring(1), k, A);
            edges.push(i);
        }
    }
}
 
// Function to find a de Bruijn sequence
// of order n on k characters
function deBruijn(n, k, A)
{
 
    // Clearing global variables
    seen = new Set();
    edges = [];
    var startingNode = A[0].repeat(n-1);
    dfs(startingNode, k, A);
    var S = "";
     
    // Number of edges
    var l = Math.pow(k, n);
    for (var i = 0; i < l; ++i)
        S += A[edges[i]];
    S += startingNode;
    return S;
}
function strings(n, charAt)
{
    var str = "";
    for (var i = 0; i < n; i++)
        str += charAt;
    return str;
}
 
// Driver code
var n = 3, k = 2;
var A = "01";
document.write(deBruijn(n, k, A));
 
// This code is contributed by rrrtnx.
</script>
Output: 
0011101000

 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :