codeforces853D

题意:给出一个字符串,问它分别具有多少个k级字符串。一个回文串叫做1级回文串,一个回文串为k级回文串当且仅当它的左半部分和右半部分相同,且两部分都是(k-1)级回文串。

那么怎么判断呢,首先你可以先预处理好所有的回文串!   按照按照区间dp的顺序枚举好它的顺序,如果当前子串s【i,j】是一个回文串,那么肯定的是它的值是可以确定的是dp[i,j]=dp[i,mid-1||mid]+1,由于当前串还可以看成其他长度的串,如长度为4的串可以看成为3的串,或者可以看成长度为2的串,为1的串!

下面是ac代码:
                             

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char sz[5100];
 4 int ans[5100];
 5 int dp[5100][5100],hw[5100][5100];
 6 int len;
 7 int main(){
 8     scanf("%s",sz+1);
 9     len=strlen(sz+1);
10     for(int i=1;i<=len;i++) hw[i][i]=1;
11     for(int i=1;i<=len;i++){
12         for(int j=1;j<=len;j++){
13             if(i-j<0||i+j>len) break;
14             if(sz[i-j]==sz[i+j]){
15                hw[i-j][i+j]=1;
16             }else break;
17         }
18         for(int j=1;j<=len;j++){
19             if(i-j+1<0||i+j>len) break;
20             if(sz[i-j+1]==sz[i+j]){
21                 hw[i-j+1][i+j]=1;
22             }else break;
23         }
24     }
25     for(int i=len;i>=1;i--){
26         for(int j=i;j<=len;j++){
27             if(i==j){
28                ans[1]++;
29                dp[i][j]=1;    
30             }else{
31                 int k=(i+j)/2;
32                 if((j-i+1)%2==1){
33                    if(hw[i][j]==1){
34                        dp[i][j]=dp[i][k-1]+1;
35                        for(int p=1;p<=dp[i][j];p++) ans[p]++;
36                    }
37                 }else{
38                    if(hw[i][j]==1){
39                        dp[i][j]=dp[i][k]+1;
40                        for(int p=1;p<=dp[i][j];p++) ans[p]++;
41                    }
42                 } 
43             }
44         }
45     }
46     for(int i=1;i<len;i++) printf("%d ",ans[i]);
47     printf("%d\n",ans[len]);
48     return 0;
49 }
View Code

下面是原来wa了的代码,wa了的原因很简单,是因为我设置左右子串都必须是回文串,但是只要当前串是就可以了,

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char sz[5100];
 4 int ans[5100];
 5 int dp[5100][5100],hw[5100][5100];
 6 int len;
 7 int main(){
 8     scanf("%s",sz+1);
 9     len=strlen(sz+1);
10     for(int i=1;i<=len;i++) hw[i][i]=1;
11     for(int i=1;i<=len;i++){
12         for(int j=1;j<=len;j++){
13             if(i-j<0||i+j>len) break;
14             if(sz[i-j]==sz[i+j]){
15                hw[i-j][i+j]=1;
16                ans[1]++;
17             }else break;
18         }
19         for(int j=1;j<=len;j++){
20             if(i-j+1<0||i+j>len) break;
21             if(sz[i-j+1]==sz[i+j]){
22                 hw[i-j+1][i+j]=1;
23                 ans[1]++;
24             }else break;
25         }
26     }
27     
28     for(int i=len;i>=1;i--){
29         for(int j=i;j<=len;j++){
30             if(i==j){
31                ans[1]++;
32                dp[i][j]=1;    
33             }else{
34                 int k=(i+j)/2;
35                 if((j-i+1)%2==1){
36                    if(hw[i][k-1]==1&&hw[k+1][j]==1&&hw[i][j]==1){
37                        dp[i][j]=max(dp[i][k-1],dp[k+1][j])+1;
38                        for(int p=2;p<=dp[i][j];p++) ans[p]++;
39                    }
40                 }else{
41                    if(hw[i][k]==1&&hw[k+1][j]==1&&hw[i][j]==1){
42                        dp[i][j]=max(dp[i][k],dp[k+1][j])+1;
43                        for(int p=2;p<=dp[i][j];p++) ans[p]++;
44                    }
45                 } 
46             }
47         }
48     }
49     for(int i=1;i<len;i++) printf("%d ",ans[i]);
50     printf("%d\n",ans[len]);
51     return 0;
52 }
View Code

猜你喜欢

转载自www.cnblogs.com/pandaking/p/9977894.html