题目
已知一个大写字母构成的字符串S[1, N],求从S中删除某些字母(可以不删)后,能够成回文串的方案数。
分析
动态规划(DP)。
状态定义:f(i, j) 为区间S[i, j]上以S[j]为结束标志(必选S[j])的方案数。
转移方程:f(i, j) = Σ \Sigma Σ f(p, q),其中[p, q] ⊂ \subset ⊂ [i, j]且S[p-1] = S[j]
说明
注意使用long long 防止数据溢出。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char str[66];
long long dp[66][66];
int main()
{
int T;
scanf("%d", &T);
while (T --) {
scanf("%s", str);
int N = strlen(str);
for (int i = 1; i <= N; ++ i) {
for (int j = 1; j <= N; ++ j) {
if (i == j) {
dp[i][j] = 1LL;
} else {
dp[i][j] = 0LL;
}
}
}
for (int w = 2; w <= N; ++ w) {
for (int s = 1; s+w-1 <= N; ++ s) {
int t = s+w-1;
dp[s][t] = 1LL;
for (int p = s; p < t; ++ p) {
if (str[p-1] == str[t-1]) {
dp[s][t] ++;
for (int q = p+1; q < t; ++ q) {
dp[s][t] += dp[p+1][q];
}
}
}
}
}
long long sum = 0LL;
for (int i = 1; i <= N; ++ i) {
sum += dp[1][i];
}
printf("%lld\n", sum);
}
return 0;
}