De Bruijn sequence | Set 1

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++
Java
Python3
C#
Javascript
// 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 twicevoid 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 charactersstring 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 codeint main(){    int n = 3, k = 2;    string A = "01";     cout << deBruijn(n, k, A);     return 0;}
// Java implementation of// the above approachimport 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 implementation of# the above approachimport math seen = set()edges = [] # Modified DFS in which no edge# is traversed twicedef 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 charactersdef 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 coden = 3k = 2A = "01" print(deBruijn(n, k, A)) # This code is contributed by shubhamsingh10
// C# implementation of// the above approachusing 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
<script> // Javascript implementation of// the above approachvar seen = new Set();var edges = []; // Modified DFS in which no edge// is traversed twicefunction 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 charactersfunction 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 codevar n = 3, k = 2;var A = "01";document.write(deBruijn(n, k, A)); // This code is contributed by rrrtnx.</script>
0011101000
 
29AjayKumar
rrrtnx
SHUBHAMSINGH10
DFS
Euler-Circuit
Technical Scripter 2018
Graph
Strings
Technical Scripter
Strings
DFS
Graph
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Find if there is a path between two vertices in a directed graph
Find if there is a path between two vertices in an undirected graph
Introduction to Data Structures
What is Data Structure: Types, Classifications and Applications
K Centers Problem | Set 1 (Greedy Approximate Algorithm)
Write a program to reverse an array or string
Reverse a string in Java
C++ Data Types
Write a program to print all permutations of a given string
Python program to check if a string is palindrome or not