hdu 4632
题意:给你一个长度为n的字符串,求包含几个回文序列?
分析:dp[i][j]表示区间[l,r]内包含的回文序列的个数,
dp[i][j] = dp[i+1][j] + dp[i][j-1] - dp[i+1][j-1]; if (s[i] == s[j] ) dp[i][j] += dp[i+1][j-1]+1;
也可以用别的递推方式,比如dp[i][j] = SUM(dp[k][j-1]+1)+1( s[k] == s[j] ,i<=k<j )
可以递推求dp[i][j] = dp[i+1][j] + tmp ;这样时间还是O(n^2);
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<vector> 7 #include<cstdlib> 8 #include<set> 9 using namespace std; 10 const int N = 1000+10; 11 const int Mod = 10007; 12 int dp[N][N]; 13 char s[N]; 14 int n; 15 int dfs(int l,int r){ 16 if (r<l) return 0; 17 if (dp[l][r]) return dp[l][r]; 18 if (l == r) return dp[l][r] = 1; 19 dp[l][r] = 0; 20 dp[l][r] +=( dfs(l,r-1)+dfs(l+1,r) - dfs(l+1,r-1) ); 21 if (s[l] == s[r]) dp[l][r] += dfs(l+1,r-1)+1; 22 return dp[l][r] %= Mod; 23 } 24 int main(){ 25 int T,cas = 0; scanf("%d",&T); 26 while (T--){ 27 scanf("%s",s); 28 memset(dp,0,sizeof(dp)); 29 n = strlen(s); 30 dfs(0,n-1); 31 printf("Case %d: %d\n",++cas,dp[0][n-1]); 32 } 33 return 0; 34 }