题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4632
注意到任意一个回文子序列收尾两个字符一定是相同的,于是可以区间dp,用dp[i][j]表示原字符串中[i,j]位置中出现的回文子序列的个数,有递推关系:
dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]
如果i和j位置出现的字符相同,那么dp[i][j]可以由dp[i+1][j-1]中的子序列加上这两个字符构成回文子序列,也就是
dp[i][j]+=dp[i+1][j-1],注意边界特判一下就可以了
(以上摘自杭电解题报告原文)
里面忘了取模,结果输出的是负数,一直WA,然后ans = (ans+10007)%10007;
贴代码:
1 #include <cstdio> 2 #include <cstring> 3 #define N 1005 4 int dp[N][N]; 5 int main() 6 { 7 char a[N]; 8 int n; 9 scanf("%d",&n); 10 for(int t=1; t<=n; ++t) 11 { 12 scanf("%s",a); 13 int len=strlen(a); 14 memset(dp,0,sizeof(dp)); 15 for(int i=0; i<len; ++i) 16 dp[i][i] =1; 17 for(int k=1; k<len; ++k) 18 { 19 for(int i=0; i+k <len; ++i) 20 { 21 int j = i+k; 22 dp[i][j] += dp[i+1][j] + dp[i][j-1] - dp[i+1][j-1]; 23 if(a[i] == a[j] ) 24 dp[i][j] += (dp[i+1][j-1] + 1); 25 dp[i][j] %=10007; 26 } 27 } 28 printf("Case %d: %d ",t,(dp[0][len-1]+10007)%10007); 29 } 30 return 0; 31 }