Empty String
Editorial
Sea el número de formas de vaciar la subcadena .
Para calcular , recorremos los índices entre y donde .
Luego, si elegimos eliminar y , primero hay que eliminar el rango (para que y queden adyacentes). Aquí, el número de formas de eliminar el rango es .
También hay que eliminar para que se elimine toda la subcadena (el número de formas de hacer esto es ).
Como podemos eliminar la subcadena y en cualquier orden, también multiplicamos esto por (nótese que dividimos los tamaños por dos porque eliminamos las letras de a pares).
Así, nuestra transición sería
tal que .
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
#define N 500
#define MOD 1000000007
int add(int a, int b) {
if ((a += b) >= MOD) a -= MOD;
return a;
}
int mul(int a, int b) { return int(1LL * a * b % MOD); }
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
int n, i, j, k;
static int dp[N + 1][N + 1], choose[N / 2 + 1][N / 2 + 1];
static string s;
cin >> s;
n = (int)s.size();
choose[0][0] = 1;
for (i = 1; i <= n / 2; ++i) {
choose[i][0] = 1;
for (int j = 1; j <= i; ++j)
choose[i][j] = add(choose[i - 1][j], choose[i - 1][j - 1]);
}
for (i = 0; i + 1 <= n; ++i) dp[i + 1][i] = 1;
for (i = n - 1; i >= 0; --i)
for (j = i + 1; j < n; j += 2) {
for (k = i + 1; k <= j; k += 2)
if (s[i] == s[k]) {
int temp = mul(dp[i + 1][k - 1], dp[k + 1][j]);
temp = mul(temp, choose[(j - i + 1) / 2][(k - i + 1) / 2]);
dp[i][j] = add(dp[i][j], temp);
}
}
cout << dp[0][n - 1] << '\n';
}import java.io.*;
public class EmptyStrings {
private static final int MOD = 1000000007;
private static int add(int a, int b) {
int sum = a + b;
return sum >= MOD ? sum - MOD : sum;
}
private static int mul(int a, int b) { return (int)(1L * a * b % MOD); }
public static void main(String[] args) throws Exception {
char[] s = new BufferedReader(new InputStreamReader(System.in))
.readLine()
.toCharArray();
final int n = s.length;
int[][] dp = new int[n + 1][n + 1];
int[][] choose = new int[n / 2 + 1][n / 2 + 1];
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] = add(choose[i - 1][j], choose[i - 1][j - 1]);
}
for (int i = 0; i + 1 <= n; i++) { dp[i + 1][i] = 1; }
for (int i = n - 1; i >= 0; i--) {
for (int j = i + 1; j < n; j += 2) {
for (int k = i + 1; k <= j; k += 2)
if (s[i] == s[k]) {
int temp = mul(dp[i + 1][k - 1], dp[k + 1][j]);
temp = mul(temp, choose[(j - i + 1) / 2][(k - i + 1) / 2]);
dp[i][j] = add(dp[i][j], temp);
}
}
}
System.out.println(dp[0][n - 1]);
}
}N = 500
MOD = 10**9 + 7
def add(a: int, b: int) -> int:
return (a + b) % MOD
def mul(a: int, b: int) -> int:
return (a * b) % MOD
s = input()
n = len(s)
dp = [[0] * (N + 1) for _ in range(N + 1)]
choose = [[0] * (N // 2 + 1) for _ in range(N // 2 + 1)]
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] = add(choose[i - 1][j], choose[i - 1][j - 1])
for i in range(0, n):
dp[i + 1][i] = 1
for i in range(n - 1, -1, -1):
for j in range(i + 1, n, 2):
for k in range(i + 1, j + 1, 2):
if s[i] == s[k]:
temp = mul(dp[i + 1][k - 1], dp[k + 1][j])
temp = mul(temp, choose[(j - i + 1) // 2][(k - i + 1) // 2])
dp[i][j] = add(dp[i][j], temp)
print(dp[0][n - 1])