Binary string with given frequencies of sums of consecutive pairs of characters


A binary string is a series of 0s and 1s in computer science and mathematics. The sum of two adjacent characters is indicated by sums of subsequent pairs of characters. For example to understand the below topic, the total number or digits of the succeeding pairs in the string "11010" is 1+1=2, 1+0=1, and 0+1=1. The goal is to locate a binary string that satisfies the specified frequencies using the frequencies of these sums as a guide. Applications of this issue can be found in fields like information theory and coding theory.

Methods

To find a binary string with given frequencies of sums of consecutive pairs of characters, we can use the following methods −

Method 1: Brute Force

Method 2: Backtracking

Method 3: Dynamic Programming

Method 1: Brute Force

A set of algorithms known as brute force approaches solve problems by thoroughly examining every potential solution, usually without the use of optimisations or heuristics. A brute force strategy entails creating every conceivable binary string and then determining if the frequencies of sums of consecutive pairs of characters match the specified frequencies in order to obtain a binary string with the required frequencies of sums of consecutive pairs of characters.

Syntax

Here's a syntax of a brute force method to find a binary string with given frequencies of sums of consecutive pairs of characters

// Initialize variables
int n = length of binary string
int freq[] = array of frequencies of sums
string result = ""

// Loop through all possible binary strings of length n
for (int i = 0; i < pow(2, n); i++) {
   string binary = binary representation of i with padding of zeros to length n

   // Check if the binary string satisfies the frequency constraints
   int sumFreq[] = array of frequencies of sums for binary
   bool valid = true
   for (int j = 0; j < n - 1; j++) {
      if (sumFreq[j] != freq[j]) {
         valid = false
         break
      }
   }

   // If the binary string satisfies the frequency constraints, save it as result
   if (valid) {
      result = binary
      break
   }
}

// Print the result
print result

Algorithm

Step 1 − Produce every binary string of length n that is conceivable.

Step 2 − Determine the sums of every binary string's adjacent character pairs.

Step 3 − Verify that these sums' frequencies match the specified frequencies.

Step 4 − If a match is discovered, provide the binary string back.

Step 5 − Return "No binary string found" if no match is discovered.

Example 1

Here's an example C++ code that implements a brute force method to find all binary strings of length n with a given frequency of sums of consecutive pairs of characters −

These implementations generate_binary_strings function takes as inputs a vector to hold the results (results), the required frequency of summing of successive pairs (freq), and the length of the binary strings (n). It uses a nested loop over the integers from 0 to 2n-1 to construct all conceivable binary strings of length n. After that, it examines each string to see if it adheres to the specified frequency and the restriction that no two consecutive characters cannot be 1. A string is included in the results vector if it meets these requirements. A binary string is constructed in the function known as the main function and is then written or shown on the screen.

#include <iostream>
#include <vector>
using namespace std;

void generate_binary_strings(int n, int freq, vector<string>& results) {
   for (int i = 0; i < (1 << n); i++) {
      string s(n, '0');
      int count = 0;
      for (int j = 0; j < n-1; j++) {
         if (i & (1 << j)) {
            s[j] = '1';
            count++;
         }
      }
      if (count == freq) {
         bool valid = true;
         for (int j = 0; j < n-1; j++) {
            if (s[j] == '1' && s[j+1] == '1') {
               valid = false;
               break;
            }
         }
         if (valid) {
            results.push_back(s);
         }
      }
   }
}

int main() {
   int n = 4; // length of binary strings
   int freq = 2; // desired frequency of sums of consecutive pairs
   vector<string> results;
   generate_binary_strings(n, freq, results);
   cout << "Binary strings of length " << n << " with frequency " << freq << ":" << endl;
   for (const auto& s : results) {
      cout << s << endl;
   }
   return 0;
}

Output

Binary strings of length 4 with frequency 2:
1010
1010

Method 2: Backtracking

To solve combinatorial issues, backtracking is a powerful algorithmic technique that is frequently employed. Finding a binary string with a certain frequency of sums of successive pairs of letters is one of these problems. In this problem, the two integers n and k, which represent the length of the binary string and the frequency of the sums of successive pairs of characters, respectively, are provided.

Syntax

backtrack(string s, int freq[], int n, int index)
   if index == n
      return true  // base case: solution found
    
   for i = 0 to 1
      s[index] = i
      if satisfies_constraints(s, freq, index)
         if backtrack(s, freq, n, index+1)
            return true  // solution found
            
   return false  // backtrack
    
satisfies_constraints(string s, int freq[], int index)
   // check if s[0:index] satisfies the given constraints

Algorithm

Step 1 − Begin with an n-length empty string.

Step 2 − Produce all feasible sums of a binary string of length n that contains consecutive character pairs.

Step 3 − Using backtracking, create every binary string that might possibly be made up of 0s and 1s while making sure that each sum's frequency corresponds to the specified frequency.

Step 4 − Return a valid binary string if one is discovered.

Step 5 − Return "No binary string found" if no suitable binary string could be located.

This method's temporal complexity can, in the worst case, be O(2n), depending on how many valid binary strings need to be verified.

Example 2

The backtrack function takes as input a vector freq of length n that represents desired frequencies of sums of consecutive pairs of characters reference to binary string of length n that will contain binary string being constructed, an integer pos that represents the current position in the binary string being constructed, and integer sum that represents sum of previous two characters (o).

In main function of the example, we build frequency vector called freq and use it to call findBinaryStringWithFrequencies. A valid binary string is reported to the console if one is discovered. If not, a failure notice is displayed.

#include <iostream>
#include <vector>
using namespace std;

bool backtrack(vector<int>& freq, string& binary, int pos, int sum) {
   if (pos == binary.length()) {
      return true;
   }

   for (int i = 0; i <= 1; i++) {
      int new_sum = sum + (i * (pos > 0 ? binary[pos-1] - '0' : 0));
      if (freq[new_sum] > 0) {
         freq[new_sum]--;
         binary[pos] = '0' + i;
         if (backtrack(freq, binary, pos+1, new_sum)) {
            return true;
         }
         freq[new_sum]++;
      }
   }

   return false;
}

string findBinaryStringWithFrequencies(vector<int> freq) {
   int n = freq.size();
   string binary(n, '0');
   if (backtrack(freq, binary, 0, 0)) {
      return binary;
   } else {
      return "";
   }
}

int main() {
   vector<int> freq = {1, 2, 1, 0, 0, 1};
   string binary = findBinaryStringWithFrequencies(freq);
   if (binary.empty()) {
      cout << "No binary string found." << endl;
   } else {
      cout << "Binary string: " << binary << endl;
   }
   return 0;
}

Output

No binary string found.

Method 3: Dynamic Programming

Dynamic programming is a well-known method in computer science for resolving optimisation issues by splitting them into smaller issues and then constructing a solution to the main issue from the solutions to those smaller issues. The creation of binary strings with predetermined sums of consecutive character pair frequencies is one use for dynamic programming.

Syntax

The pseudocode for the above dynamic programming approach is given below −

Function finds binary string(frequencies):
   N = length of binary string
   k = maximum sum of consecutive pairs of characters that need to be achieved
   YT[N+1] [k+1] = 0
   YT [0][0] = 1
   for L in interval (1, N+1):
      for P in interval(k+1):
         for prep in {0, 1}:
         if j - prep >= 0:
         YT[L][P] += YT[L-1] [P-prep]
   answer = 0
   for P in interval(k+1):
      if frequency[P]!= -1:
         answer += YT[N][P] * frequency[P]
   return answer.

In the above pseudocode, the frequencies parameter is a list of size k+1, where the i-th element represents the frequency of the sum of consecutive pairs of characters equal to i. If the frequency of a particular sum is not given, the corresponding frequency value will be -1. The function returns the number of binary strings that satisfy the given frequency constraints.

Algorithm

Step 1 − Create a dp array with n+1 elements and initialise it to 0.

Step 2 − Increment the matching entry in the dp array for each possible sum of the characters in successive pairings.

Step 3 − Find every binary string that could possibly include a mixture of 0s and 1s using dynamic programming, making sure that each sum's frequency corresponds to the specified frequency.

Step 4 − Return a valid binary string if one is discovered.

Step 5 − Return "No binary string found" if no suitable binary string could be located.

The time complexity of this method depends on the quantity of valid binary strings that must be verified, however in some circumstances it may be quicker than the earlier techniques.

Example 3

An illustration of how to handle the problem of finding a binary string with specified frequencies of sums of successive pairs of characters using dynamic programming.

In this version, the number of binary strings of length i that include j pairs of consecutive 1s and k pairs of successive 0s are stored in a 3-dimensional DP array called dp[i][j][k]. Starting with the basic cases for i = 1, we use recurrence relation to compute the DP array for i = 2 to n. According to this relationship, the total number of binary strings of length i that contain j consecutive pairs of 1s and k consecutive pairs of 0s equals the sum of the strings that contained j consecutive pairs of 1s and k consecutive pairs in the step before it (dp[i-1][j][k]).

#include<bits/stdc++.h>
using namespace std;

// Function to find the binary string
string binaryStringWithFrequencies(int n, int freq0, int freq1, int freq2) {
   string ans = "";
    
   // DP array to store the number of strings
   // with a given frequency of sums
   vector<vector<vector<int>>>dp(n + 1, vector<vector<int>>(freq1 + 1, vector<int>(freq2 + 1)));
    
   // Initialize DP array for base cases
   dp[1][0][0] = 1;
   if(freq1 > 0) dp[1][1][0] = 1;
   if(freq2 > 0) dp[1][0][1] = 1;
    
   // Compute DP array for remaining cases
   for(int i = 2; i <= n; i++) {
      for(int j = 0; j <= freq1; j++) {
         for(int k = 0; k <= freq2; k++) {
            if(j + k > i) break;  // No possible string with sum of consecutive pairs > i
            dp[i][j][k] = dp[i-1][j][k];
            if(j > 0) dp[i][j][k] += dp[i-1][j-1][k];
            if(k > 0) dp[i][j][k] += dp[i-1][j][k-1];
         }
      }
   }
    
   // Trace back the DP array to find the binary string
   int j = freq1, k = freq2;
   for(int i = n; i >= 1; i--) {
      if(j > 0 && dp[i-1][j-1][k] > 0) {
         ans += '1';
         j--;
      }
      else {
         ans += '0';
         k--;
      }
   }
    
   // Reverse the string to get the correct order
   reverse(ans.begin(), ans.end());
    
   // Return the binary string
   return ans;
}

// Driver code
int main() {
   int n = 5;
   int freq0 = 2, freq1 = 1, freq2 = 1;
   string ans = binaryStringWithFrequencies(n, freq0, freq1, freq2);
   cout << ans << endl;  // Output: 00110
   return 0;
}

Output

00001

Conclusion

Finally, it should be noted that finding a binary string with specific frequencies of the sums of consecutive character pairs is a difficult challenge that calls for considerable thought. It is feasible to effectively address this problem and produce an appropriate binary string by using mathematical methods and algorithms like linear programming. The difficulty of the issue, however, rises as the amount of the input, and it may take a lot of processing power to discover the best answer. However, this issue may be properly dealt with and the needed binary string can be obtained by using the appropriate methods and tools.

Updated on: 31-Jul-2023

86 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements