Open In App

Maximize sum of assigned weights by flipping at most K bits in given Binary String

Given a binary string str of length N and an integer K, the task is to find the maximum possible sum of assigned weights that can be obtained by flipping at most K bits in the given binary string. The weight assigned to the characters of this string are as follows:

Examples:



Input: str = “10100”, K = 2
Output: 7
Explanation:
1st flip: Flip the character at index 1, the string becomes “11100”.
2nd flip: Flip the character at index 3, the string becomes “11110”.
The weight of the resulting string is 1 + 2 + 2 + 2 + 0 = 7, which is maximum.

Input: str = “100101”, K = 1
Output: 6
Explanation:
1st flip: Flip the character at index 5, the string becomes “100111”.
The weight of the resulting string is 1 + 0 + 0 + 1 + 2 + 2 = 6, which is maximum.



Approach: The weight of character ‘1’ appearing after a ‘1’ is greatest among all characters, so to maximize the sum, try to create as many such 1s possible. The segments of 0s to be flipped to 1 can be prioritized as follows:

Flip the character of the given string as per the above priority to maximize the weight and then find the weight of the resulting string after at most K flips. 

Below is the implementation of this approach:




// C++ program of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find maximum sum of
// weights of binary string after
// at most K flips
int findMax(string s, int n, int k)
{
    int ans = 0;
 
    // Stores lengths of substrings
    // of the form 1..00..1s
    int l = 0;
 
    // Stores the index of last 1
    // encountered in the string
    int ind = -1;
 
    // Stores the index of first 1
    // encountered
    int indf = -1;
 
    // Stores lengths of all substrings
    // having of 0s enclosed by 1s
    // at both ends
    multiset<int> ls;
 
    // Traverse the string
    for (int i = 0; i < n; i++) {
        // If character is 0
        if (s[i] == '0')
            l++;
 
        // If character is 1
        // First Priority
        else if (s[i] == '1'
                 && l > 0 && ans != 0) {
            ls.insert(l);
            l = 0;
        }
 
        // Second Priority
        if (s[i] == '1') {
            ind = i;
            l = 0;
            if (indf == -1)
                indf = i;
 
            // Add according to the
            // first priority
            if (i > 0 && s[i - 1] == '1')
                ans += 2;
            else
                ans += 1;
        }
    }
 
    // Stores length of the shortest
    // substring of 0s
    int curr;
 
    // Convert shortest substrings
    // of 0s to 1s
    while (k > 0 && !ls.empty()) {
        curr = *ls.begin();
 
        // Add according to the
        // first priority
        if (k >= curr) {
            ans += (2 * curr + 1);
            k -= curr;
        }
 
        // Add according to the
        // third priority
        else {
            ans += (2 * k);
            k = 0;
        }
        ls.erase(ls.begin());
    }
 
    // If more 0s can be made into 1,
    // then check for 0s at ends
    if (k > 0) {
        // Update the ans
        ans += (2 * min(k,
                        n - (ind + 1))
                - 1);
        k -= min(k, n - (ind + 1));
 
        if (ind > -1)
            ans++;
    }
 
    // If K is non-zero, then flip 0s
    // at the beginning
    if (k > 0) {
        ans += (min(indf, k) * 2 - 1);
 
        if (indf > -1)
            ans++;
    }
 
    // Return the final weights
    return ans;
}
 
// Driver Code
int main()
{
    // Given string str
    string str = "1110000101";
 
    int N = str.length();
 
    // Given K flips
    int K = 3;
 
    // Function Call
    cout << findMax(str, N, K);
 
    return 0;
}




// Java program of the above approach
import java.util.*;
 
class GFG
{
 
  // Function to find maximum sum of
  // weights of binary String after
  // at most K flips
  static int findMax(String s, int n, int k)
  {
    var ans = 0;
 
    // Stores lengths of subStrings
    // of the form 1..00..1s
    var l = 0;
 
    // Stores the index of last 1
    // ensize()ered in the String
    var ind = -1;
 
    // Stores the index of first 1
    // ensize()ered
    var indf = -1;
 
    // Stores lengths of all subStrings
    // having of 0s enclosed by 1s
    // at both ends
    var ls = new TreeSet<Integer>();
 
    // Traverse the String
    for (var i = 0; i < n; i++) {
      // If character is 0
      if (s.charAt(i) == '0')
        l += 1;
 
      // If character is 1
      // First Priority
      else if ((s.charAt(i) == '1') && (l > 0)
               && (ans != 0)) {
        ls.add(l);
        l = 0;
      }
      // Second Priority
      if (s.charAt(i) == '1') {
        ind = i;
        l = 0;
        if (indf == -1)
          indf = i;
 
        // add according to the
        // first priority
        if ((i > 0) && (s.charAt(i - 1) == '1'))
          ans += 2;
        else
          ans += 1;
      }
    }
 
    // Stores length of the shortest
    // subString of 0s
    var curr = 0;
 
    // Convert shortest subStrings
    // of 0s to 1s
    while (k > 0 && (ls.size() != 0)) {
 
      for(var i : ls)
      {
        curr = i;
        break;
      }
 
      // add according to the
      // first priority
      if (k >= curr) {
        ans += (2 * curr + 1);
        k -= curr;
      }
 
      // add according to the
      // third priority
      else {
        ans += (2 * k);
        k = 0;
      }
 
      ls.remove(curr);
    }
 
    // If more 0s can be made into 1,
    // then check for 0s at ends
    if (k > 0) {
      // Update the ans
      ans += (2 * Math.min(k, n - (ind + 1)) - 1);
      k -= Math.min(k, n - (ind + 1));
 
      if (ind > -1)
        ans += 1;
    }
 
    // If K is non-zero, then flip 0s
    // at the beginning
    if (k > 0) {
      ans += (Math.min(indf, k) * 2 - 1);
 
      if (indf > -1)
        ans += 1;
    }
 
    // Return the final weights
    return ans;
  }
 
  // Driver Code
 
  public static void main(String[] args)
  {
    // Given String str
    var s = "1110000101";
 
    var N = s.length();
 
    // Given K flips
    var K = 3;
 
    // Function Call
    System.out.println(findMax(s, N, K));
  }
}
 
// This code is contributed by phasing17




# Python 3 program of the above approach
 
# Function to find maximum sum of
# weights of binary string after
# at most K flips
def findMax( s, n, k):
 
    ans = 0;
 
    # Stores lengths of substrings
    # of the form 1..00..1s
    l = 0;
 
    # Stores the index of last 1
    # encountered in the string
    ind = -1;
 
    # Stores the index of first 1
    # encountered
    indf = -1;
 
    # Stores lengths of all substrings
    # having of 0s enclosed by 1s
    # at both ends
    ls = set([])
 
    # Traverse the string
    for i in range(n):
        # If character is 0
        if (s[i] == '0'):
            l+=1
 
        # If character is 1
        # First Priority
        elif (s[i] == '1'
                 and l > 0 and ans != 0):
            ls.add(l);
            l = 0;
 
        # Second Priority
        if (s[i] == '1') :
            ind = i;
            l = 0;
            if (indf == -1):
                indf = i;
 
            # Add according to the
            # first priority
            if (i > 0 and s[i - 1] == '1'):
                ans += 2;
            else:
                ans += 1;
 
    # Stores length of the shortest
    # substring of 0s
    curr = 0
 
    # Convert shortest substrings
    # of 0s to 1s
    while (k > 0 and len(ls)!=0):
        for i in ls:
          curr = i
          break
 
        # Add according to the
        # first priority
        if (k >= curr):
            ans += (2 * curr + 1);
            k -= curr;
 
        # Add according to the
        # third priority
        else :
            ans += (2 * k);
            k = 0;
        
        ls.remove(curr);
     
    # If more 0s can be made into 1,
    # then check for 0s at ends
    if (k > 0) :
        # Update the ans
        ans += (2 * min(k,
                        n - (ind + 1))
                - 1);
        k -= min(k, n - (ind + 1));
 
        if (ind > -1):
            ans+=1
 
    # If K is non-zero, then flip 0s
    # at the beginning
    if (k > 0):
        ans += (min(indf, k) * 2 - 1);
 
        if (indf > -1):
            ans+=1
    
    # Return the final weights
    return ans
 
# Driver Code
if __name__ == "__main__":
   
    # Given string str
    s = "1110000101";
 
    N = len(s)
 
    # Given K flips
    K = 3;
 
    # Function Call
    print(findMax(s, N, K));
 
    # This code is contributed by chitranayal




// C# program of the above approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
  // Function to find maximum sum of
  // weights of binary string after
  // at most K flips
  static int findMax(string s, int n, int k)
  {
    var ans = 0;
 
    // Stores lengths of substrings
    // of the form 1..00..1s
    var l = 0;
 
    // Stores the index of last 1
    // encountered in the string
    var ind = -1;
 
    // Stores the index of first 1
    // encountered
    var indf = -1;
 
    // Stores lengths of all substrings
    // having of 0s enclosed by 1s
    // at both ends
    var ls = new SortedSet<int>();
 
    // Traverse the string
    for (var i = 0; i < n; i++) {
      // If character is 0
      if (s[i] == '0')
        l += 1;
 
      // If character is 1
      // First Priority
      else if ((s[i] == '1') && (l > 0)
               && (ans != 0)) {
        ls.Add(l);
        l = 0;
      }
      // Second Priority
      if (s[i] == '1') {
        ind = i;
        l = 0;
        if (indf == -1)
          indf = i;
 
        // Add according to the
        // first priority
        if ((i > 0) && (s[i - 1] == '1'))
          ans += 2;
        else
          ans += 1;
      }
    }
 
    // Stores length of the shortest
    // substring of 0s
    var curr = 0;
 
    // Convert shortest substrings
    // of 0s to 1s
    while (k > 0 && (ls.Count != 0)) {
 
      foreach(var i in ls)
      {
        curr = i;
        break;
      }
 
      // Add according to the
      // first priority
      if (k >= curr) {
        ans += (2 * curr + 1);
        k -= curr;
      }
 
      // Add according to the
      // third priority
      else {
        ans += (2 * k);
        k = 0;
      }
 
      ls.Remove(curr);
    }
 
    // If more 0s can be made into 1,
    // then check for 0s at ends
    if (k > 0) {
      // Update the ans
      ans += (2 * Math.Min(k, n - (ind + 1)) - 1);
      k -= Math.Min(k, n - (ind + 1));
 
      if (ind > -1)
        ans += 1;
    }
 
    // If K is non-zero, then flip 0s
    // at the beginning
    if (k > 0) {
      ans += (Math.Min(indf, k) * 2 - 1);
 
      if (indf > -1)
        ans += 1;
    }
 
    // Return the final weights
    return ans;
  }
 
  // Driver Code
 
  public static void Main(string[] args)
  {
    // Given string str
    var s = "1110000101";
 
    var N = s.Length;
 
    // Given K flips
    var K = 3;
 
    // Function Call
    Console.WriteLine(findMax(s, N, K));
  }
}
 
// This code is contributed by phasing17




// JavaScript program of the above approach
 
// Function to find maximum sum of
// weights of binary string after
// at most K flips
function findMax( s, n, k)
{
    let ans = 0;
 
    // Stores lengths of substrings
    // of the form 1..00..1s
    let l = 0;
 
    // Stores the index of last 1
    // encountered in the string
    let ind = -1;
 
    // Stores the index of first 1
    // encountered
    let indf = -1;
 
    // Stores lengths of all substrings
    // having of 0s enclosed by 1s
    // at both ends
    let ls = new Set()
 
    // Traverse the string
    for (var i = 0; i < n; i++)
    {
        // If character is 0
        if (s[i] == '0')
            l+=1
 
        // If character is 1
        // First Priority
        else if ( (s[i] == '1') && (l > 0) && (ans != 0))
        {
            ls.add(l);
            l = 0;
        }
        // Second Priority
        if (s[i] == '1')
        {
            ind = i;
            l = 0;
            if (indf == -1)
                indf = i;
 
            // Add according to the
            // first priority
            if ((i > 0) && (s[i - 1] == '1'))
                ans += 2;
            else
                ans += 1;
        }
    }
 
    // Stores length of the shortest
    // substring of 0s
    let curr = 0
 
     
     
    // Convert shortest substrings
    // of 0s to 1s
    while (k > 0 && (ls.length!=0))
    {
         
        ls1 = Array.from(ls)
        ls1.sort()
         
        for (let i of ls1)
        {
          curr = i
          break
        }
 
        // Add according to the
        // first priority
        if (k >= curr)
        {
            ans += (2 * curr + 1);
            k -= curr;
        }
 
        // Add according to the
        // third priority
        else
        {
            ans += (2 * k);
            k = 0;
        }
         
        ls.delete(curr);
    }
     
    // If more 0s can be made into 1,
    // then check for 0s at ends
    if (k > 0)
    {
        // Update the ans
        ans += (2 *  Math.min(k, n - (ind + 1))  - 1);
        k -=  Math.min(k, n - (ind + 1));
 
        if (ind > -1)
            ans+=1
    }
     
    // If K is non-zero, then flip 0s
    // at the beginning
    if (k > 0)
    {
        ans += ( Math.min(indf, k) * 2 - 1);
 
        if (indf > -1)
            ans +=1
    }
    
    // Return the final weights
    return ans
}
 
// Driver Code
 
// Given string str
let s = "1110000101";
 
let N = s.length
 
// Given K flips
let K = 3;
 
// Function Call
console.log(findMax(s, N, K));
 
 
// This code is contributed by phasing17

Output: 
14

 

Time Complexity: O(N)
Auxiliary Space: O(N)


Article Tags :