题目大意:给定一个字符串,让你求这个字符串中有多少个回文子序列 如:abab 中a,b,a,b,aa,bb,aba,bab,一共8个回文子序列。
既然是DP的问题,当然还是找状态转移方程吧,本题的状态转移方程是:
如果s[i]!=s[j]
dp[i][j]=(dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1])%mod //注意因为公式中有减号存在,可能出现负数,处理一下。
如果s[i]==s[j]
dp[i][j]=(dp[i+1][j]+dp[i][j-1]+1)%mod; //即包含a,b的一个端点,包含a,b两个端点。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define mod 10007
char s[1100];
int dp[1100][1100];
int main()
{
int T;
scanf("%d",&T);
int cas=0;
while(T--)
{
cas++;
cin>>s;
memset(dp,0,sizeof(dp));
int len=strlen(s);
for(int i=0;i<len;i++)
dp[i][i]=1;
for(int i=0;i<len-1;i++)
dp[i][i+1]=(s[i]==s[i+1])?3:2;
for(int k=2;k<len;k++)
{
for(int i=0;i+k<len;i++)
{
int j=i+k;
//dp[i][j]=(dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1]+mod)%mod;
if(s[i]==s[j])
dp[i][j]=(dp[i][j-1]+dp[i+1][j]+1)%mod;
else
dp[i][j]=(dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1]+mod)%mod;
}
}
cout<<"Case "<<cas<<": "<<dp[0][len-1]<<endl;
}
return 0;
}