区间dp
其实就是统计从整个字符串中取出任意数量的字符使之成为palindrom,当s[i]==s[j]时,根据容斥原理,dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1]+dp[i+1][j-1]+1;其中,dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1]是[i,j]区间内的长度不超过j-i的回文串,dp[i+1][j-1]是区间内的长度最长的回文串,1是指s[i]s[j]组成的回文串。
同理当s[i]!=s[j]的`时,dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1]。
注意初始化dp[i][i]=1,并且2的60次方要用long long存储(比如每个字符都相同的情况)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define TYPE long long
using namespace std;
const int MAX=70;
TYPE dp[MAX][MAX];
int main(){
int T;
char s[MAX];
scanf("%d",&T);
getchar();
while(T--){
gets(s);
int len=strlen(s);
memset(dp,0,MAX*MAX*sizeof(TYPE));
for(int i=0;i<MAX;i++)
dp[i][i]=1;
for(int i=2;i<=len;i++){
for(int j=0;j<=len-i;j++){
if(s[j]==s[j+i-1])
dp[j][j+i-1]=dp[j][j+i-2]+dp[j+1][j+i-1]+1;
else
dp[j][j+i-1]=dp[j][j+i-2]+dp[j+1][j+i-1]-(i==2?0:dp[j+1][j+i-2]);
}
}
printf("%lld\n",dp[0][len-1]);
}
return 0;
}