题目链接:
http://hihocoder.com/contest/msbop2015qual/problem/2
分析:
记状态为dp[i][j]表示从i到j这一段中的回文个数。
状态转移方程:
dp[i][j]=dp[i+1][j]+dp[i][j-1]+1 if(s[i]==s[j])
dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1] if(s[i]!=s[j])
当s[i]==s[j]时,中间部分需要考虑两次,一次是与左侧的s[i]或者自身内部,一次是与右边的s[j]或者中间部分的回文加上s[i]和s[j]。
代码。
<span style="font-size:14px;">#include <iostream>
#include <cstdio>
#include <cstring>
#define MOD 100007
using namespace std;
const int maxn = 1005;
int dp[maxn][maxn];
string str;
int dfs(int f,int t)
{
if(dp[f][t]!=-1) return dp[f][t];
if(f>t) return 0;
if(f==t) return dp[f][t]=1;
if(str[f-1]==str[t-1])
dp[f][t]=(dfs(f,t-1)+dfs(f+1,t)+1)%MOD;
else
dp[f][t]=(dfs(f,t-1)-dfs(f+1,t-1)+dfs(f+1,t))%MOD;
//cout<<"dp["<<f<<"]["<<t<<"]="<<dp[f][t]<<endl;
return dp[f][t];
}
int main()
{
//freopen("in.txt","r",stdin);
int t;
cin>>t;
for(int i=1;i<=t;i++)
{
memset(dp,-1,sizeof(dp));
cin>>str;
//cout<<str<<endl;
printf("Case #%d: %d\n",i,dfs(1,str.length()));
}
return 0;
}
</span>