题意
T组测试数据,每组给你一个序列,问这个序列有多少个回文子序列,mod104+7mod\quad 10^4+7mod104+7
思路
dp[i][j]dp[i][j]dp[i][j]表示[i,j][i,j][i,j]区间有多少个回文子序列
①s[i]!=s[j]s[i]!=s[j]s[i]!=s[j],通过容斥可得dp[i][j]=dp[i+1][j]+dp[i][j−1]−dp[i+1][j−1]dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1]dp[i][j]=dp[i+1][j]+dp[i][j−1]−dp[i+1][j−1]
②s[i]==s[j]s[i]==s[j]s[i]==s[j],这种情况比①情况又多了一些答案, i 和 j 可以形成一个回文子序列,i 和 j 组上dp[i+1][j−1]dp[i+1][j-1]dp[i+1][j−1]也可以形成新的回文子序列,所以dp[i][j]=dp[i+1][j]+dp[i][j−1]+1;dp[i][j] = dp[i + 1][j] + dp[i][j - 1] + 1;dp[i][j]=dp[i+1][j]+dp[i][j−1]+1;
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 5;
const int MOD = 1e4 + 7;
typedef long long LL;
int n;
char s[MAXN];
LL dp[MAXN][MAXN];
int main()
{
int T, CASE = 1; scanf("%d%*c", &T);
while (T--)
{
scanf("%s%*c", s);
n = strlen(s);
for (int i = 0; i < n; i++) dp[i][i] = 1;
for (int len = 2; len <= n; len++)
{
for (int i = 0; i + len - 1 < n; i++)
{
int j = i + len - 1;
if (s[i] == s[j]) dp[i][j] = dp[i + 1][j] + dp[i][j - 1] + 1;
else dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1];
dp[i][j] = (dp[i][j] + MOD) % MOD;
}
}
printf("Case %d: %d\n", CASE++, dp[0][n - 1]);
}
return 0;
}
/*
4
a
aaaaa
goodafternooneveryone
welcometoooxxourproblems
*/