📌  相关文章
📜  通过递归删除所有相邻重复项来清空给定字符串的方法计数

📅  最后修改于: 2022-05-13 01:56:04.864000             🧑  作者: Mango

通过递归删除所有相邻重复项来清空给定字符串的方法计数

给定一个字符串S ,一次就可以删除两个相邻的相等字符。删除后,已删除字符的两个端点都连接在一起。计算清空字符串的方法总数。

例子:

方法:以上问题可以通过以下方式解决 动态规划。请按照以下步骤解决问题:

  • 让我们定义一个二维 dp 表dp[i][j],它将存储范围 [i, j] 的答案。
  • 定义递归方法来解决问题。
  • 要计算dp[i][j] ,请遍历ij之间的所有索引k ,其中S[i] = S[k]
  • 现在对于个人k ,答案将是dp[i+1][k-1]*dp[k+1][j]*(安排删除范围的方法总数)。
  • 要计算方程的最后一项,请注意整个范围[i+1, k-1]的删除将在S[i] 和 S[k] 删除之前发生。
  • 因此,该范围内的总删除量将为(j – i + 1)/2 (因为一次删除了两个元素)。从这些移除中必须选择(j – k)/2 移除。
  • 所以最终的公式将是
  • 使用memoization不再重新计算状态。
  • 检查递归函数中的基本情况。
  • 最终答案将是dp[0][N-1]

下面是上述方法的实现:

C++
// C++ implementation for the above approach
#include 
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


输出
3

时间复杂度: O(N^3)
辅助空间: O(N^2)