Open In App

Smallest length string with repeated replacement of two distinct adjacent

Improve
Improve
Like Article
Like
Save
Share
Report

Given a string of any combination of three letters ‘a’, ‘b’, and ‘c’, find length of the smallest string that can be obtained by applying the following operation repeatedly: 

Take any two adjacent, distinct characters and replace them with the third.

Examples:  

Input : cab
Output : 2
We can select any two adjacent letters,
say 'ca' and transform it into 'b', this
leaves us with string 'bb' of length two.

Input : bcab
Output : 1
Selecting 'bc' and transforming it to 'a'
leaves us with 'aab'. We can then select
'ab' and transform it to 'c', giving 'ac'.
This can further be transformed into 'b',
which is of length one.

A naive way to do this would be to find all possible replacements, and recurse until we find the minimum string. This would take exponential time. 

Lemma: Order of letters does not effect the length or value of minimum string.

Proof By Induction 
Base case: Take string ‘ab’ and ‘ba’, they both reduce to ‘c’

Inductive Hypothesis: All strings of length <= k reduce to the same string assuming the number of occurrences of each letter in each string is the same.

Inductive Step: Take two strings of length k + 1 having same number of occurrences of each letter. Find a pair of letters that are adjacent 

in both strings. Here, two cases arise: 

  1. We manage to find such a pair of letters. We can then replace these letters with the third letter, thus getting two strings of length k having same occurrences of each letter, which by inductive hypothesis reduces to the same string. i.e. We have ‘abcacb’ and ‘accbba’ and reduce ‘ac’ in both strings, we thus get ‘abcbb’ and ‘bcbba’.
  2. We cannot find such a pair. This arises when all letters in the string are the same. In this case, the two strings themselves are the same i.e. ‘ccccccc’ and ‘ccccccc’.

Thus by induction we have proven this lemma.

Dynamic Programming Approach: We can now devise a function using Dynamic Programming to solve this problem.

C++




// C++ program to find smallest possible length
// of a string of only three characters
#include<bits/stdc++.h>
using namespace std;
 
// Program to find length of reduced string
// in a string made of three characters.
#define MAX_LEN 110
 
// To store results of subproblems
int DP[MAX_LEN][MAX_LEN][MAX_LEN];
 
// A memoized function find result recursively.
// a, b and c are counts of 'a's, 'b's and
// 'c's in str
int length(int a, int b, int c)
{
    // If this subproblem is already evaluated
    if(a < 0 or b < 0 or c < 0)
        if (DP[a][b] != -1)
            return DP[a][b];
 
    // If there is only one type of character
    if (a == 0 && b == 0)
        return (DP[a][b] = c);
    if (a == 0 && c == 0)
        return (DP[a][b] = b);
    if (b == 0 && c == 0)
        return (DP[a][b] = a);
 
    // If only two types of characters are present
    if (a == 0)
        return (DP[a][b] =
                    length(a + 1, b - 1, c - 1));
    if (b == 0)
        return (DP[a][b] =
                    length(a - 1, b + 1, c - 1));
    if (c == 0)
        return (DP[a][b] =
                    length(a - 1, b - 1, c + 1));
 
    // If all types of characters are present.
    // Try combining all pairs.
    return (DP[a][b] =
                min(length(a - 1, b - 1, c + 1),
                    min(length(a - 1, b + 1, c - 1),
                        length(a + 1, b - 1, c - 1))));
}
 
// Returns smallest possible length with given
// operation allowed.
int stringReduction(string str)
{
    int n = str.length();
 
    // Counting occurrences of three different
    // characters 'a', 'b' and 'c' in str
    int count[3] = {0};
    for (int i=0; i<n; ++i)
        count[str[i]-'a']++;
 
    // Initialize DP[][] entries as -1
    for (int i = 0; i <= count[0]; ++i)
        for (int j = 0; j < count[1]; ++j)
            for (int k = 0; k < count[2]; ++k)
                DP[i][j][k] = -1;
 
    return length(count[0], count[1], count[2]);
}
 
// Driver code
int main()
{
    string str = "abcbbaacb";
    cout << stringReduction(str);
    return 0;
}


Java




// Java program to find smallest possible length
// of a string of only three characters
import java.io.*;
class GFG
{
  static int MAX_LEN = 110;
 
  // Program to find length of reduced string
  // in a string made of three characters.
  static int[][][] DP = new int[MAX_LEN][MAX_LEN][MAX_LEN];
 
  // A memoized function find result recursively.
  // a, b and c are counts of 'a's, 'b's and
  // 'c's in str
  static int length(int a, int b, int c)
  {
 
    // If this subproblem is already
    // evaluated
    if(a < 0 || b < 0 || c < 0)
 
      // If this subproblem is already evaluated
      if (DP[a][b] != -1)
        return DP[a][b];
 
    // If there is only one type of character
    if (a == 0 && b == 0)
      return (DP[a][b] = c);
    if (a == 0 && c == 0)
      return (DP[a][b] = b);
    if (b == 0 && c == 0)
      return (DP[a][b] = a);
 
    // If only two types of characters are present
    if (a == 0)
      return (DP[a][b] =
              length(a + 1, b - 1, c - 1));
    if (b == 0)
      return (DP[a][b] =
              length(a - 1, b + 1, c - 1));
    if (c == 0)
      return (DP[a][b] =
              length(a - 1, b - 1, c + 1));
 
    // If all types of characters are present.
    // Try combining all pairs.
    DP[a][b] =
      Math.min(length(a - 1, b - 1, c + 1),
               Math.min(length(a - 1, b + 1, c - 1),
                        length(a + 1, b - 1, c - 1)));
 
    return DP[a][b];
  }
 
  // Returns smallest possible length with given
  // operation allowed.
  static int stringReduction(String str)
  {
    int n = str.length();
 
    // Counting occurrences of three different
    // characters 'a', 'b' and 'c' in str
    int[] count = new int[3];
    for (int i = 0; i < n; ++i)
      count[str.charAt(i) - 'a']++;
 
    // Initialize DP[][] entries as -1
    for (int i = 0; i <= count[0]; ++i)
      for (int j = 0; j < count[1]; ++j)
        for (int k = 0; k < count[2]; ++k)
          DP[i][j][k] = -1;
 
    return length(count[0], count[1], count[2]);
  }
 
  // Driver code
  public static void main (String[] args) {
    String str = "abcbbaacb";
    System.out.println(stringReduction(str));
  }
}
 
//  This code is contributed by rag2127


Python3




# Python3 program to find smallest possible
# length of a string of only three characters
 
# A memoized function find result recursively.
# a, b and c are counts of 'a's, 'b's and
# 'c's in str
def length(a, b, c):
     
    global DP
     
    #print(a, b, c)
     
    # If this subproblem is already
    # evaluated
    if a < 0 or b < 0 or c < 0:
        return 0
 
    if (DP[a][b] != -1):
        return DP[a][b]
 
    # If there is only one type
    # of character
    if (a == 0 and b == 0):
        DP[a][b] = c
        return c
    if (a == 0 and c == 0):
        DP[a][b] = b
        return b
    if (b == 0 and c == 0):
        DP[a][b] = a
        return a
 
    # If only two types of characters
    # are present
    if (a == 0):
        DP[a][b] = length(a + 1, b - 1,
                             c - 1)
        return DP[a][b]
         
    if (b == 0):
        DP[a][b] = length(a - 1, b + 1,
                             c - 1)
        return DP[a][b]
         
    if (c == 0):
        DP[a][b] = length(a - 1, b - 1,
                             c + 1)
        return DP[a][b]
 
    # If all types of characters are present.
    # Try combining all pairs.
    x = length(a - 1, b - 1, c + 1)
    y = length(a - 1, b + 1, c - 1)
    z = length(a + 1, b - 1, c - 1)
 
    DP[a][b] = min([x, y, z])
 
    return DP[a][b]
 
# Returns smallest possible length with
# given operation allowed.
def stringReduction(str):
     
    n = len(str)
 
    # Counting occurrences of three different
    # characters 'a', 'b' and 'c' in str
    count = [0] * 3
     
    for i in range(n):
        count[ord(str[i]) - ord('a')] += 1
 
    return length(count[0], count[1], count[2])
     
# Driver code
if __name__ == '__main__':
     
    DP = [[[-1 for i in range(110)]
               for i in range(110)]
               for i in range(110)]
 
    str = "abcbbaacb"
     
    print(stringReduction(str))
 
# This code is contributed by mohit kumar 29


C#




// C# program to find smallest possible length
// of a string of only three characters
using System;
public class GFG
{
 
  static int MAX_LEN = 110;
 
  // Program to find length of reduced string
  // in a string made of three characters.
  static int[,,] DP = new int[MAX_LEN, MAX_LEN, MAX_LEN];
 
  // A memoized function find result recursively.
  // a, b and c are counts of 'a's, 'b's and
  // 'c's in str
  static int length(int a, int b, int c)
  {
 
    // If this subproblem is already
    // evaluated
    if(a < 0 || b < 0 || c < 0)
 
      // If this subproblem is already evaluated
      if (DP[a, b, c] != -1)
        return DP[a, b, c];
 
    // If there is only one type of character
    if (a == 0 && b == 0)
      return (DP[a, b, c] = c);
    if (a == 0 && c == 0)
      return (DP[a, b, c] = b);
    if (b == 0 && c == 0)
      return (DP[a, b, c] = a);
 
    // If only two types of characters are present
    if (a == 0)
      return (DP[a, b, c] =
              length(a + 1, b - 1, c - 1));
    if (b == 0)
      return (DP[a, b, c] =
              length(a - 1, b + 1, c - 1));
    if (c == 0)
      return (DP[a, b, c] =
              length(a - 1, b - 1, c + 1));
 
    // If all types of characters are present.
    // Try combining all pairs.
    DP[a, b, c] =
      Math.Min(length(a - 1, b - 1, c + 1),
               Math.Min(length(a - 1, b + 1, c - 1),
                        length(a + 1, b - 1, c - 1)));
 
    return DP[a, b, c];
  }
 
  // Returns smallest possible length with given
  // operation allowed.
  static int stringReduction(string str)
  {
    int n = str.Length;
 
    // Counting occurrences of three different
    // characters 'a', 'b' and 'c' in str
    int[] count = new int[3];
    for (int i = 0; i < n; ++i)
      count[str[i] - 'a']++;
 
    // Initialize DP[][] entries as -1
    for (int i = 0; i <= count[0]; ++i)
      for (int j = 0; j < count[1]; ++j)
        for (int k = 0; k < count[2]; ++k)
          DP[i, j, k] = -1;
 
    return length(count[0], count[1], count[2]);
  }
 
  // Driver code
  static public void Main ()
  {
    string str = "abcbbaacb";
    Console.WriteLine(stringReduction(str));
  }
}
 
// This code is contributed by avanitrachhadiya2155


Javascript




<script>
// Javascript program to find smallest possible length
// of a string of only three characters
    let  MAX_LEN = 110;
     
    // Program to find length of reduced string
  // in a string made of three characters.
    let DP = new Array(MAX_LEN);
    for(let i = 0; i < DP.length; i++)
    {
        DP[i] = new Array(MAX_LEN);
        for(let j = 0; j < DP[i].length; j++)
        {
            DP[i][j] = new Array(MAX_LEN);
            for(let k = 0; k < MAX_LEN; k++)
            {
                DP[i][j][k] = 0;
            }
        }
    }
     
    // A memoized function find result recursively.
  // a, b and c are counts of 'a's, 'b's and
  // 'c's in str
    function length(a, b, c)
    {
        // If this subproblem is already
    // evaluated
    if(a < 0 || b < 0 || c < 0)
  
      // If this subproblem is already evaluated
      if (DP[a][b] != -1)
        return DP[a][b];
  
    // If there is only one type of character
    if (a == 0 && b == 0)
      return (DP[a][b] = c);
    if (a == 0 && c == 0)
      return (DP[a][b] = b);
    if (b == 0 && c == 0)
      return (DP[a][b] = a);
  
    // If only two types of characters are present
    if (a == 0)
      return (DP[a][b] =
              length(a + 1, b - 1, c - 1));
    if (b == 0)
      return (DP[a][b] =
              length(a - 1, b + 1, c - 1));
    if (c == 0)
      return (DP[a][b] =
              length(a - 1, b - 1, c + 1));
  
    // If all types of characters are present.
    // Try combining all pairs.
    DP[a][b] =
      Math.min(length(a - 1, b - 1, c + 1),
               Math.min(length(a - 1, b + 1, c - 1),
                        length(a + 1, b - 1, c - 1)));
  
    return DP[a][b];
    }
     
    // Returns smallest possible length with given
  // operation allowed.
    function stringReduction(str)
    {
        let n = str.length;
  
    // Counting occurrences of three different
    // characters 'a', 'b' and 'c' in str
    let count = new Array(3);
    for(let i = 0; i < 3; i++)
    {
        count[i] = 0;
    }
    for (let i = 0; i < n; ++i)
      count[str[i].charCodeAt(0) - 'a'.charCodeAt(0)]++;
  
    // Initialize DP[][] entries as -1
    for (let i = 0; i <= count[0]; ++i)
      for (let j = 0; j < count[1]; ++j)
        for (let k = 0; k < count[2]; ++k)
          DP[i][j][k] = -1;
  
    return length(count[0], count[1], count[2]);
    }
     
    // Driver code
    let str = "abcbbaacb";
    document.write(stringReduction(str));
     
// This code is contributed by unknown2108
</script>


Output

1

In the worst case, each letter is present in 1/3rd of the whole string. This leads to auxiliary space = O(N3) and time complexity = O(N3)

Space Complexity = O(N^3)
Time Complexity = O(N^3)

Mathematical Approach:

We can do better than this using three main principles: 

  1. If the string cannot be reduced further, then all letters in the string are the same.
  2. The length of minimum string is either <= 2 or equal to the length of original string, or 2 < minimum string length < original string length is never true.
  3. If each letter of the string is present an odd amount of times, after one reduction step, they shall all be present an even amount of times. The converse is also true, that is, if each letter of the string is present an even amount of times, they shall be present an odd amount of times after one reduction step.

These can be proven as follows: 

  1. If any two different letters are present, we can select these and reduce string length further.
  2. Proof by contradiction: 
    Assume we have a reduced string of length less than original string. For example ‘bbbbbbb’. Then this string must have originated from a string like ‘acbbbbbb’, ‘bbacbbbb’ or any other such combination of the same. In this case, we could have selected ‘bc’ instead of ‘ac’ and reduced further.
  3. From the recursive step above, we increase one letter by one and decrease the other two by one. So if we had a combination as (odd, odd, odd), then it would become (odd + 1, odd – 1, odd – 1) or (even, even, even). The reverse is shown in a similar fashion.

Now we can combine the above principles. 
If the string consists of the same letter repeating, it’s minimum reduced string is itself, and length is the length of the string. 
Now, the other possible options are reduced string being of one character length or two. Now if all characters are present an even number of times, or an odd number of times, the only answer that is possible is 2, because (0, 2, 0) is (even, even, even) while (0, 1, 0) is (even, odd, even) so only 2 preserves this evenness. 
In any other condition, the answer becomes 1.  

Implementation:

C++




// C++ program to find smallest possible length
// of a string of only three characters
#include<bits/stdc++.h>
using namespace std;
 
// Returns smallest possible length with given
// operation allowed.
int stringReduction(string str)
{
    int n = str.length();
 
    // Counint occurrences of three different
    // characters 'a', 'b' and 'c' in str
    int count[3] = {0};
    for (int i=0; i<n; ++i)
        count[str[i]-'a']++;
 
    // If all characters are same.
    if (count[0] == n || count[1] == n ||
        count[2] == n)
        return n;
 
    // If all characters are present even number
    // of times or all are present odd number of
    // times.
    if ((count[0] % 2) == (count[1] % 2) &&
        (count[1] % 2) == (count[2] % 2))
        return 2;
 
    // Answer is 1 for all other cases.
    return 1;
}
 
// Driver code
int main()
{
    string str = "abcbbaacb";
    cout << stringReduction(str);
    return 0;
}


Java




// Java program to find smallest possible length
// of a string of only three characters
public class GFG {
 
// Returns smallest possible length with given
// operation allowed.
    static int stringReduction(String str) {
        int n = str.length();
 
        // Counint occurrences of three different
        // characters 'a', 'b' and 'c' in str
        int count[] = new int[3];
        for (int i = 0; i < n; ++i) {
            count[str.charAt(i) - 'a']++;
        }
 
        // If all characters are same.
        if (count[0] == n || count[1] == n
                || count[2] == n) {
            return n;
        }
 
        // If all characters are present even number
        // of times or all are present odd number of
        // times.
        if ((count[0] % 2) == (count[1] % 2)
                && (count[1] % 2) == (count[2] % 2)) {
            return 2;
        }
 
        // Answer is 1 for all other cases.
        return 1;
    }
 
// Driver code
    public static void main(String[] args) {
        String str = "abcbbaacb";
        System.out.println(stringReduction(str));
    }
}
// This code is contributed by PrinciRaj1992


Python3




# Python3 program to find smallest possible
# length of a string of only three characters
 
# Returns smallest possible length
# with given operation allowed.
def stringReduction(str):
 
    n = len(str)
 
    # Counint occurrences of three different
    # characters 'a', 'b' and 'c' in str
    count = [0] * 3
    for i in range(n):
        count[ord(str[i]) - ord('a')] += 1
 
    # If all characters are same.
    if (count[0] == n or count[1] == n or
                         count[2] == n):
        return n
 
    # If all characters are present even number
    # of times or all are present odd number of
    # times.
    if ((count[0] % 2) == (count[1] % 2) and
        (count[1] % 2) == (count[2] % 2)):
        return 2
 
    # Answer is 1 for all other cases.
    return 1
 
# Driver code
if __name__ == "__main__":
     
    str = "abcbbaacb"
    print(stringReduction(str))
 
# This code is contributed by ita_c


C#




// C# program to find smallest possible length
// of a string of only three characters
using System;
public class GFG {
 
// Returns smallest possible length with given
// operation allowed.
    static int stringReduction(String str) {
        int n = str.Length;
 
        // Counint occurrences of three different
        // characters 'a', 'b' and 'c' in str
        int []count = new int[3];
        for (int i = 0; i < n; ++i) {
            count[str[i] - 'a']++;
        }
 
        // If all characters are same.
        if (count[0] == n || count[1] == n
                || count[2] == n) {
            return n;
        }
 
        // If all characters are present even number
        // of times or all are present odd number of
        // times.
        if ((count[0] % 2) == (count[1] % 2)
                && (count[1] % 2) == (count[2] % 2)) {
            return 2;
        }
 
        // Answer is 1 for all other cases.
        return 1;
    }
 
// Driver code
    public static void Main() {
        String str = "abcbbaacb";
        Console.WriteLine(stringReduction(str));
    }
}
// This code is contributed by 29AjayKumar


Javascript




<script>
 
// Javascript program to find smallest
// possible length of a string of only
// three characters
 
// Returns smallest possible length
// with given operation allowed.
function stringReduction(str)
{
    var n = str.length;
 
    // Counvar occurrences of three different
    // characters 'a', 'b' and 'c' in str
    var count = Array.from({length: 3}, (_, i) => 0);
    for(var i = 0; i < n; ++i)
    {
        count[str.charAt(i).charCodeAt(0) -
                        'a'.charCodeAt(0)]++;
    }
 
    // If all characters are same.
    if (count[0] == n ||
        count[1] == n ||
        count[2] == n)
    {
        return n;
    }
 
    // If all characters are present even number
    // of times or all are present odd number of
    // times.
    if ((count[0] % 2) == (count[1] % 2) &&
        (count[1] % 2) == (count[2] % 2))
    {
        return 2;
    }
 
    // Answer is 1 for all other cases.
    return 1;
}
 
// Driver code
var str = "abcbbaacb";
document.write(stringReduction(str));
 
// This code is contributed by Princi Singh
 
</script>


PHP




<?php
// PHP program to find smallest possible length
// of a string of only three characters
 
// Returns smallest possible length with
// given operation allowed.
function stringReduction($str)
{
    $n = strlen($str);
 
    // Counint occurrences of three different
    // characters 'a', 'b' and 'c' in str
    $count = array_fill(0, 3, 0);
    for ($i = 0; $i < $n; ++$i)
        $count[ord($str[$i]) - ord('a')]++;
 
    // If all characters are same.
    if ($count[0] == $n || $count[1] == $n ||
        $count[2] == $n)
        return $n;
 
    // If all characters are present even number
    // of times or all are present odd number of
    // times.
    if (($count[0] % 2) == ($count[1] % 2) &&
        ($count[1] % 2) == ($count[2] % 2))
        return 2;
 
    // Answer is 1 for all other cases.
    return 1;
}
 
// Driver code
$str = "abcbbaacb";
print(stringReduction($str));
     
// This code is contributed by mits
?>


Output

1

Time Complexity: O(n) 
Auxiliary Space: O(1)



Last Updated : 07 Jan, 2024
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads