dp[i][j]表示s[i]到s[j]这一字串内回文串的个数
容易想到可以按子串长度递增进行递推,
比如当处理长度为4的子串情况时长度小于4的子串情况已经都处理出来了
决策:
s[i]==s[j]:
暂令此时dp[i][j]新增以s[i]s[j]为两端的回文串,即dp[i][j]=1+dp[i+1][j-1]
s[i]==s[j]
暂令dp[i][j]=0
下面处理从较短长度继承过来的回文数量
长度为4的话便从长度为3的数量继承过来,即dp[i+1][j]+dp[i][j-1],但其中间有重叠的数量,于是再-dp[i+1][j-1]
注意要用64位整数,为此贡献一次WA、、、
#include<stdio.h>
#include<string.h>
#define MAXN 65
#define ll long long
char s[MAXN];
ll dp[MAXN][MAXN];
int main()
{
int cas;
scanf("%d",&cas);
while(cas--)
{
scanf("%s",s);
int n=strlen(s);
for(int len=0;len<n;len++)
for(int i=0;i<n;i++)
{
int j=i+len;
if(j>=n) break;
if(s[i]==s[j])
{
dp[i][j]=1;
int l=i+1,r=j-1;
if(l<=r)
dp[i][j]+=dp[l][r];
}
else
dp[i][j]=0;
if(i!=j)
{
dp[i][j]+=dp[i+1][j]+dp[i][j-1];
int l=i+1,r=j-1;
if(l<=r)
dp[i][j]-=dp[l][r];
}
}
printf("%lld\n",dp[0][n-1]);
}
return 0;
}