Open In App

Maximizing Distance in Binary Strings

Last Updated : 19 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array of binary strings arr[] of size N (1 <= N <= 103). The task is to find the maximum distance between any pair of these binary strings. The distance between two binary strings is calculated as the sum of their lengths after excluding the common prefix.

Examples:

Input: arr[] = { “01011”, “010110”, “0111”}
Output: 6
Explanation: The strings with the maximum distance between them are “010110” and “0111”, where the common prefix is “01”, Hence, the sum of their lengths after excluding the common prefix: 4 + 2 = 6.

Input: arr[] = {“001”, “1”, “111111”}
Output: 9
Explanation: The string “001” and “111111” have no common prefix, hence, the sum of their lengths after excluding the common prefix: 3 + 6 = 9.

Maximizing Distance in Binary Strings using Trie:

We need to use of a Trie data structure to efficiently find the maximum distance between binary strings in the given array. We’ll store the length of longest suffix from current node till its bottom leaf node. By traversing the Trie, we can find the maximum distance by considering the sum of lengths of non-overlapping substrings of binary strings, resulting in the desired maximum distance calculation. This approach is extremely more efficient than comparing every pair of binary strings directly.

Step-by-step approach:

TrieNode Class:

  • Create a TrieNode class with attributes val for storing the length of string after excluding the common prefix, an ending flag, and left and right child pointers.

Build Trie:

  • Create a buildTree() function to build a Trie from an array of binary strings (nums).
  • Initialize a pointer cur to the root node and iterate through each binary string in given array arr[].
  • For each character in the binary string:
    • If it’s ‘0’, traverse to the left child (0) in the Trie. If the left child doesn’t exist, create it and update its val.
    • If it’s ‘1’, traverse to the right child (1) in the Trie. If the right child doesn’t exist, create it and update its val.
  • Mark the current node as an ending node (isEnding = true)

Calculate Maximum Distance:

  • Create a maxDistance() function to calculate the maximum distance between binary strings using the constructed Trie.
  • Create the Trie root node and build the Trie structure using buildTree() by above mentioned steps.
  • Initialize max_distance = 0 and a queue (q) for breadth-first traversal.
  • Start with the root node and push it into the queue.
  • While the queue is not empty:
    • Dequeue the front node cur.
    • If cur has left or right children:
      • If it has both left and right children, calculate the maximum distance as the sum of their val and update max_distance.
    • If cur is an ending node, calculate the maximum distance considering either the left or right child with val and update max_distance.
    • Enqueue the left and right children of cur, if they exist.
  • Return the max_distance.

Below is the implementation of the above approach:

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
// Define a class for a TrieNode
class TrieNode {
public:
    // Store the length of longest suffix from
    // current node till its bottom leaf node
    int val;
 
    // Indicates if this node is the end of a
    // number
    bool isEnding;
 
    // Pointer to the left child (0)
    TrieNode* left;
 
    // Pointer to the right child (1)
    TrieNode* right;
 
    TrieNode(int val)
        : val(val)
        , isEnding(false)
        , left(nullptr)
        , right(nullptr)
    {
    }
};
 
// Function to build the Trie tree
void buildTree(TrieNode* root, vector<string>& nums)
{
    for (int i = 0; i < nums.size(); i++) {
        TrieNode* cur = root;
        int j = 0, len = nums[i].length();
        while (j < len) {
            if (nums[i][j] == '0') {
                if (cur->left == nullptr) {
                    cur->left = new TrieNode(len - j);
                }
                else {
                    cur->left->val
                        = max(cur->left->val, len - j);
                }
                cur = cur->left;
            }
            else {
                if (cur->right == nullptr) {
                    cur->right = new TrieNode(len - j);
                }
                else {
                    cur->right->val
                        = max(cur->right->val, len - j);
                }
                cur = cur->right;
            }
            j++;
        }
        cur->isEnding = true;
    }
    return;
}
 
// Function to find the maximum distance in the Trie
int maxDistance(vector<string>& nums)
{
    TrieNode* root = new TrieNode(0);
    buildTree(root, nums);
    int max_distance = 0;
    queue<TrieNode*> q;
    q.push(root);
    while (!q.empty()) {
        TrieNode* cur = q.front();
        q.pop();
        if (cur->left || cur->right) {
            if (cur->left && cur->right) {
 
                // Calculate the maximum distance for
                // common prefixes with both left
                // and right branches
                max_distance
                    = max(max_distance,
                          cur->left->val + cur->right->val);
            }
            else if (cur->isEnding) {
 
                // Calculate the maximum distance for
                // common prefixes with either
                // left or right branch
                max_distance
                    = max(max_distance,
                          cur->left ? cur->left->val
                                    : cur->right->val);
            }
        }
        if (cur->left)
            q.push(cur->left);
        if (cur->right)
            q.push(cur->right);
    }
    return max_distance;
}
 
// Drivers code
int main()
{
    vector<string> nums = { "01011", "010110", "0111" };
    int max_distance = maxDistance(nums);
 
    // Function Call
    cout << max_distance;
    return 0;
}


Java




// Java code for the above approach:
 
import java.util.LinkedList;
import java.util.Queue;
 
// Define a class for a TrieNode
class TrieNode {
    // Store the length of longest suffix from
    // current node till its bottom leaf node
    int val;
 
    // Indicates if this node is the end of a
    // number
    boolean isEnding;
 
    // Pointer to the left child (0)
    TrieNode left;
 
    // Pointer to the right child (1)
    TrieNode right;
 
    TrieNode(int val)
    {
        this.val = val;
        isEnding = false;
        left = right = null;
    }
}
 
class GFG {
    // Function to build the Trie tree
    static void buildTree(TrieNode root, String[] nums)
    {
        for (int i = 0; i < nums.length; i++) {
            TrieNode cur = root;
            int j = 0, len = nums[i].length();
 
            while (j < len) {
                if (nums[i].charAt(j) == '0') {
                    if (cur.left == null) {
                        cur.left = new TrieNode(len - j);
                    }
                    else {
                        cur.left.val = Math.max(
                            cur.left.val, len - j);
                    }
 
                    cur = cur.left;
                }
                else {
                    if (cur.right == null) {
                        cur.right = new TrieNode(len - j);
                    }
                    else {
                        cur.right.val = Math.max(
                            cur.right.val, len - j);
                    }
 
                    cur = cur.right;
                }
 
                j++;
            }
 
            cur.isEnding = true;
        }
    }
 
    // Function to find the maximum distance in the Trie
    static int maxDistance(String[] nums)
    {
        TrieNode root = new TrieNode(0);
        buildTree(root, nums);
        int max_distance = 0;
        Queue<TrieNode> q = new LinkedList<>();
        q.add(root);
 
        while (!q.isEmpty()) {
            TrieNode cur = q.poll();
 
            if (cur.left != null || cur.right != null) {
                if (cur.left != null && cur.right != null) {
 
                    // Calculate the maximum distance for
                    // common prefixes with both left
                    // and right branches
                    max_distance = Math.max(
                        max_distance,
                        cur.left.val + cur.right.val);
                }
                else if (cur.isEnding) {
 
                    // Calculate the maximum distance for
                    // common prefixes with either
                    // left or right branch
                    max_distance = Math.max(
                        max_distance, cur.left != null
                                          ? cur.left.val
                                          : cur.right.val);
                }
            }
 
            if (cur.left != null)
                q.add(cur.left);
 
            if (cur.right != null)
                q.add(cur.right);
        }
 
        return max_distance;
    }
 
    // Drivers code
    public static void main(String[] args)
    {
        String[] nums = { "01011", "010110", "0111" };
        int max_distance = maxDistance(nums);
 
        // Function Call
        System.out.println(max_distance);
    }
}
 
// This code is contributed by ragul21


Python3




# Python Implementation;
class TrieNode:
    def __init__(self, val):
        self.val = val
        self.isEnding = False
        self.left = None
        self.right = None
 
 
def buildTree(root, nums):
    for num in nums:
        cur = root
        j = 0
        length = len(num)
 
        while j < length:
            if num[j] == '0':
                if cur.left is None:
                    cur.left = TrieNode(length - j)
                else:
                    cur.left.val = max(cur.left.val, length - j)
 
                cur = cur.left
            else:
                if cur.right is None:
                    cur.right = TrieNode(length - j)
                else:
                    cur.right.val = max(cur.right.val, length - j)
 
                cur = cur.right
 
            j += 1
 
        cur.isEnding = True
 
 
def maxDistance(nums):
    root = TrieNode(0)
    buildTree(root, nums)
    max_distance = 0
    queue = []
    queue.append(root)
 
    while queue:
        cur = queue.pop(0)
 
        if cur.left or cur.right:
            if cur.left and cur.right:
                max_distance = max(max_distance, cur.left.val + cur.right.val)
            elif cur.isEnding:
                max_distance = max(
                    max_distance, cur.left.val if cur.left else cur.right.val)
 
        if cur.left:
            queue.append(cur.left)
 
        if cur.right:
            queue.append(cur.right)
 
    return max_distance
 
 
nums = ["01011", "010110", "0111"]
max_distance = maxDistance(nums)
print(max_distance)
 
# This code is contributed by Tapesh(tapeshdua420)


C#




using System;
using System.Collections.Generic;
 
// Define a class for a TrieNode
class TrieNode
{
    // Store the length of the longest suffix from
    // the current node till its bottom leaf node
    public int Val { get; set; }
 
    // Indicates if this node is the end of a number
    public bool IsEnding { get; set; }
 
    // Pointer to the left child (0)
    public TrieNode Left { get; set; }
 
    // Pointer to the right child (1)
    public TrieNode Right { get; set; }
 
    public TrieNode(int val)
    {
        Val = val;
        IsEnding = false;
        Left = null;
        Right = null;
    }
}
 
class Program
{
    // Function to build the Trie tree
    static void BuildTree(TrieNode root, List<string> nums)
    {
        foreach (var num in nums)
        {
            TrieNode cur = root;
            int j = 0, len = num.Length;
            while (j < len)
            {
                if (num[j] == '0')
                {
                    if (cur.Left == null)
                    {
                        cur.Left = new TrieNode(len - j);
                    }
                    else
                    {
                        cur.Left.Val = Math.Max(cur.Left.Val, len - j);
                    }
                    cur = cur.Left;
                }
                else
                {
                    if (cur.Right == null)
                    {
                        cur.Right = new TrieNode(len - j);
                    }
                    else
                    {
                        cur.Right.Val = Math.Max(cur.Right.Val, len - j);
                    }
                    cur = cur.Right;
                }
                j++;
            }
            cur.IsEnding = true;
        }
    }
 
    // Function to find the maximum distance in the Trie
    static int MaxDistance(List<string> nums)
    {
        TrieNode root = new TrieNode(0);
        BuildTree(root, nums);
        int maxDistance = 0;
        Queue<TrieNode> queue = new Queue<TrieNode>();
        queue.Enqueue(root);
 
        while (queue.Count > 0)
        {
            TrieNode cur = queue.Dequeue();
 
            if (cur.Left != null || cur.Right != null)
            {
                if (cur.Left != null && cur.Right != null)
                {
                    // Calculate the maximum distance for common prefixes with both left and right branches
                    maxDistance = Math.Max(maxDistance, cur.Left.Val + cur.Right.Val);
                }
                else if (cur.IsEnding)
                {
                    // Calculate the maximum distance for common prefixes with either left or right branch
                    maxDistance = Math.Max(maxDistance, cur.Left != null ? cur.Left.Val : cur.Right.Val);
                }
            }
 
            if (cur.Left != null)
                queue.Enqueue(cur.Left);
 
            if (cur.Right != null)
                queue.Enqueue(cur.Right);
        }
 
        return maxDistance;
    }
 
    // Drivers code
    static void Main()
    {
        List<string> nums = new List<string> { "01011", "010110", "0111" };
        int maxDistance = MaxDistance(nums);
 
        // Display the result
        Console.WriteLine(maxDistance);
    }
}


Javascript




class TrieNode {
    constructor(val) {
        this.val = val;
        this.isEnding = false;
        this.left = null;
        this.right = null;
    }
}
 
// Function to build the Trie tree
function buildTree(root, nums) {
    for (let i = 0; i < nums.length; i++) {
        let cur = root;
        let j = 0, len = nums[i].length;
        while (j < len) {
            if (nums[i][j] === '0') {
                if (!cur.left) {
                    cur.left = new TrieNode(len - j);
                } else {
                    cur.left.val = Math.max(cur.left.val, len - j);
                }
                cur = cur.left;
            } else {
                if (!cur.right) {
                    cur.right = new TrieNode(len - j);
                } else {
                    cur.right.val = Math.max(cur.right.val, len - j);
                }
                cur = cur.right;
            }
            j++;
        }
        cur.isEnding = true;
    }
}
 
// Function to find the maximum distance in the Trie
function maxDistance(nums) {
    const root = new TrieNode(0);
    buildTree(root, nums);
    let max_distance = 0;
    const queue = [root];
 
    while (queue.length > 0) {
        const cur = queue.shift();
 
        if (cur.left || cur.right) {
            if (cur.left && cur.right) {
               
                // Calculate the maximum distance for
                // common prefixes with both left
                // and right branches
                max_distance =
                  Math.max(max_distance, cur.left.val + cur.right.val);
            } else if (cur.isEnding) {
               
                // Calculate the maximum distance for
                // common prefixes with either
                // left or right branch
                max_distance =
                  Math.max(max_distance, cur.left ? cur.left.val : cur.right.val);
            }
        }
 
        if (cur.left) queue.push(cur.left);
        if (cur.right) queue.push(cur.right);
    }
 
    return max_distance;
}
 
// Driver code
const nums = ["01011", "010110", "0111"];
const max_distance = maxDistance(nums);
 
// Function Call
console.log(max_distance);


Output

6










Time Complexity: O(N * M), where N is the number of binary strings and M is the average length of the binary strings.
Auxiliary Space: O(N * M)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads