题意
T组测试数据,每组给你一个序列,问这个序列有多少个回文子序列, m o d 1 0 4 + 7 mod\quad 10^4+7 mod104+7
思路
d
p
[
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],通过容斥可得
d
p
[
i
]
[
j
]
=
d
p
[
i
+
1
]
[
j
]
+
d
p
[
i
]
[
j
−
1
]
−
d
p
[
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 组上
d
p
[
i
+
1
]
[
j
−
1
]
dp[i+1][j-1]
dp[i+1][j−1]也可以形成新的回文子序列,所以
d
p
[
i
]
[
j
]
=
d
p
[
i
+
1
]
[
j
]
+
d
p
[
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
*/