Count of ways to empty given String by recursively removing all adjacent duplicates (original) (raw)

Last Updated : 23 Jul, 2025

Given a string S, in one move it is allowed to remove two adjacent equal characters. After the removal, both endpoints of the removed characters are joined. Calculate the total number of ways to empty the string.

Example:

Input: S = aabccb
Output: 3
Explanation:
1. aabccb -> aabb -> aa
2. aabccb -> aabb -> bb
3. aabccb -> bccb -> bb
Hence, there are a total of 3 ways to empty the string after a valid set of moves.

Input: S = aabbc
Output: 0
Explanation: The string is of odd length, so it is not possible to empty the whole string.

Approach: The above problem can be solved with the help ofDynamic Programming. Follow the steps below to solve the problem:

dp[i+1][k-1]*dp[k+1][j]*{}^{(j-i + 1)/2}C_{(j - k)/2}

Below is the implementation of the above approach:

C++ `

// C++ implementation for the above approach #include <bits/stdc++.h> using namespace std;

// Define the dp table globally int dp[505][505], choose[502][502];

// Recursive function to calculate the dp // values for range [L, R] int calc(int l, int r, string& s) {

// The range is odd length
if (abs(r - l) % 2 == 0) {
    return 0;
}

if (l > r) {
    return dp[l][r] = 1;
}

// The state is already calculated
if (dp[l][r] != -1) {
    return dp[l][r];
}

// If the length is 2
if ((r - l) == 1) {
    if (s[l] == s[r]) {
        dp[l][r] = 1;
    }
    else {
        dp[l][r] = 0;
    }
    return dp[l][r];
}

// Total answer for this state
int ans = 0;
for (int k = l + 1; k <= r; k += 2) {

    // Variable to store the current answer.
    int temp = 1;

    // Remove characters s[l] and s[i].
    if (s[l] == s[k]) {
        temp = calc(l + 1, k - 1, s)
               * calc(k + 1, r, s)
               * choose[(r - l + 1) / 2]
                       [(r - k) / 2];
        ans += temp;
    }
}
return dp[l][r] = ans;

}

int waysToClearString(string S) {

// Initialize all the states of dp to -1
memset(dp, -1, sizeof(dp));

// Calculate all Combinations
int n = S.length();
choose[0][0] = 1;
for (int i = 1; i <= n / 2; ++i) {
    choose[i][0] = 1;
    for (int j = 1; j <= i; ++j) {
        choose[i][j]
            = (choose[i - 1][j]
               + choose[i - 1][j - 1]);
    }
}
return calc(0, n - 1, S);

}

// Driver Code int main() { string S = "aabccb";

cout << waysToClearString(S);

return 0;

}

Java

// Java program for the above approach import java.io.*; class GFG {

// Define the dp table globally static int [][]dp = new int[505][505]; static int [][]choose = new int[502][502];

// Recursive function to calculate the dp // values for range [L, R] static int calc(int l, int r, String s) {

// The range is odd length
        if (Math.abs(r - l) % 2 == 0) {
            return 0;
        }

        if (l > r) {
            return dp[l][r] = 1;
        }

        // The state is already calculated
        if (dp[l][r] != -1) {
            return dp[l][r];
        }

        // If the length is 2
        if ((r - l) == 1) {
            if (s.charAt(l) == s.charAt(r)) {
                dp[l][r] = 1;
            }
            else {
                dp[l][r] = 0;
            }
            return dp[l][r];
        }

        // Total answer for this state
        int ans = 0;
        for (int k = l + 1; k <= r; k += 2) {

            // Variable to store the current answer.
            int temp = 1;

            // Remove characters s[l] and s[i].
            if (s.charAt(l) == s.charAt(k)) {
                temp = calc(l + 1, k - 1, s)
                    * calc(k + 1, r, s)
                    * choose[((r - l + 1) / 2)]
                    [((r - k) / 2)];
                ans += temp;
            }
        }
        return dp[l][r] = ans;

}

static int waysToClearString(String S) {

// Initialize all the states of dp to -1
// Initialize all the states of dp to -1
for(int i=0;i<505;i++){
    for(int j=0;j<505;j++)
        dp[i][j] = -1;
}

        // Calculate all Combinations
        int n = S.length();
        choose[0][0] = 1;
        for (int i = 1; i <= (n / 2); ++i) {
            choose[i][0] = 1;
            for (int j = 1; j <= i; ++j) {
                choose[i][j]
                    = (choose[i - 1][j]
                        + choose[i - 1][j - 1]);
            }
        }
        return calc(0, n - 1, S);

}

// Driver Code public static void main (String[] args) { String S = "aabccb";

System.out.println(waysToClearString(S));

} }

// This code is contributed by sanjoy_62.

Python3

Python3 implementation for the above approach

import numpy as np

Define the dp table globally

dp = np.zeros((505,505)); choose = np.zeros((502,502));

Recursive function to calculate the dp

values for range [L, R]

def calc(l, r, s) :

# The range is odd length
if (abs(r - l) % 2 == 0) :
    return 0;

if (l > r) :
    dp[l][r] = 1;
    return dp[l][r]

# The state is already calculated
if (dp[l][r] != -1) :
    return dp[l][r];

# If the length is 2
if ((r - l) == 1) :
    if (s[l] == s[r]) :
        dp[l][r] = 1;
    
    else :
        dp[l][r] = 0;
    
    return dp[l][r];

# Total answer for this state
ans = 0;

for k in range(l + 1, r + 1, 2) :

    # Variable to store the current answer.
    temp = 1;

    # Remove characters s[l] and s[i].
    if (s[l] == s[k]) :
        temp = calc(l + 1, k - 1, s) * calc(k + 1, r, s) * choose[(r - l + 1) // 2][(r - k) // 2];
        ans += temp;
    

dp[l][r] = ans;
return dp[l][r]

def waysToClearString(S) :

# Initialize all the states of dp to -1
#memset(dp, -1, sizeof(dp));

for i in range(505):
    for j in range(505) :
        dp[i][j] = -1

# Calculate all Combinations
n = len(S);
choose[0][0] = 1;
for i in range(1, (n // 2) + 1) : 
    choose[i][0] = 1;
    for j in range(1, i + 1) :
        choose[i][j]= choose[i - 1][j] + choose[i - 1][j - 1];

return calc(0, n - 1, S);

Driver Code

if name == "main" :

S = "aabccb";

print(waysToClearString(S));

# This code is contributed by AnkThon

C#

// C# implementation for the above approach using System; using System.Collections.Generic;

class GFG{ // Define the dp table globally static int [,]dp = new int[505,505]; static int [,]choose = new int[502,502];

// Recursive function to calculate the dp // values for range [L, R] static int calc(int l, int r, string s) {

// The range is odd length
if (Math.Abs(r - l) % 2 == 0) {
    return 0;
}

if (l > r) {
    return dp[l,r] = 1;
}

// The state is already calculated
if (dp[l,r] != -1) {
    return dp[l,r];
}

// If the length is 2
if ((r - l) == 1) {
    if (s[l] == s[r]) {
        dp[l,r] = 1;
    }
    else {
        dp[l,r] = 0;
    }
    return dp[l,r];
}

// Total answer for this state
int ans = 0;
for (int k = l + 1; k <= r; k += 2) {

    // Variable to store the current answer.
    int temp = 1;

    // Remove characters s[l] and s[i].
    if (s[l] == s[k]) {
        temp = calc(l + 1, k - 1, s)
               * calc(k + 1, r, s)
               * choose[(r - l + 1) / 2,(r - k) / 2];
        ans += temp;
    }
}
return dp[l,r] = ans;

}

static int waysToClearString(string S) {

// Initialize all the states of dp to -1
for(int i=0;i<505;i++){
    for(int j=0;j<505;j++)
        dp[i,j] = -1;
}

// Calculate all Combinations
int n = S.Length;
choose[0,0] = 1;
for (int i = 1; i <= n / 2; ++i) {
    choose[i,0] = 1;
    for (int j = 1; j <= i; ++j) {
        choose[i,j]
            = (choose[i - 1,j]
               + choose[i - 1,j - 1]);
    }
}
return calc(0, n - 1, S);

}

// Driver Code public static void Main() { string S = "aabccb";

Console.Write(waysToClearString(S));

} }

// This code is contributed by ipg2016107.

JavaScript

`

Time Complexity: O(N^3)
Auxiliary Space: O(N^2)