De Bruijn sequence | Set 1

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:

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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;
}

chevron_right


Output:

0011101000


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.