LightOJ1025 The Specials Menu(区间DP)
给一个字符串,问有几种删字符的方式使删后的非空字符串是个回文串。
当然区间DP:dp[i][j]表示子串stri...strj的方案数
感觉不好转移,可能重复算了。我手算了"AAA"这个数据,然后就搞出转移的方式:
d[i][j] = ∑ d[i'][j']+1 (i<=i'<=j'<=j 且 str[i']==str[j'])
这个区间DP和经典例题相邻石子合并一样,枚举长度然后枚举起点,这样保证计算过程的拓扑有序。时间复杂度O(strlen4)。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 char str[66]; 5 long long d[66][66]; 6 int main(){ 7 int t; 8 scanf("%d",&t); 9 for(int cse=1; cse<=t; ++cse){ 10 scanf("%s",str); 11 int n=strlen(str); 12 memset(d,0,sizeof(d)); 13 for(int len=1; len<=n; ++len){ 14 for(int k=0; k+len<=n; ++k){ 15 d[k][k+len-1]=len; 16 for(int i=0; i<len; ++i){ 17 for(int j=i+1; j<len; ++j){ 18 if(str[k+i]!=str[k+j]) continue; 19 d[k][k+len-1]+=d[k+i+1][k+j-1]+1; 20 } 21 } 22 } 23 } 24 printf("Case %d: %lld\n",cse,d[0][n-1]); 25 } 26 return 0; 27 }