Smallest length string with repeated replacement of two distinct adjacent

4.5

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++ 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 (DP[a][b]1 != -1)
        return DP[a][b]1;

    // If there is only one type of character
    if (a == 0 && b == 0)
        return (DP[a][b]1 = c);
    if (a == 0 && c == 0)
        return (DP[a][b]1 = b);
    if (b == 0 && c == 0)
        return (DP[a][b]1 = a);

    // If only two types of characters are present
    if (a == 0)
        return (DP[a][b]1 =
                    length(a + 1, b - 1, c - 1));
    if (b == 0)
        return (DP[a][b]1 =
                    length(a - 1, b + 1, c - 1));
    if (c == 0)
        return (DP[a][b]1 =
                    length(a - 1, b - 1, c + 1));

    // If all types of characters are present.
    // Try combining all pairs.
    return (DP[a][b]1 =
                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;
}

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.

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

Output:

1

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

This article is contributed by Aditya Kamath. 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 write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

GATE CS Corner    Company Wise Coding Practice

Recommended Posts:



4.5 Average Difficulty : 4.5/5.0
Based on 16 vote(s)










Writing code in comment? Please use ide.geeksforgeeks.org, generate link and share the link here.