欢迎访问我的个人网站==》 jiashubing.cn

POJ 1159 Palindrome(LCS)

题目链接http://poj.org/problem?id=1159

题目大意:给定一串字符,添加最少的字符,使之成为回文串。

Sample Input

5
Ab3bd

Sample Output

2

分析:这道题目之前有做过,就是将原字符串逆序得到另一个字符串,求它们的最长公共子序列,这样就能求得它的可以构成回文的最长字符数,用n减去即为添加最少可使之成为回文的数目。

可恨的是之前一直超内存,看了别人的解题报告,原来定义dp[MAX][MAX]时,不用int型,而是short型,内存只占int的一半(见上一篇日志)


另外逆序字符串可以不用新开一个数组,也可以直接在原数组上从后往前循环。

代码如下:
 1 # include<stdio.h>
 2 # include<string.h>
 3 
 4 #define MAX 5005
 5 
 6 int max(int a,int b,int c){
 7     int temp;
 8     temp = a>b ? a :b;
 9     return temp>c ?temp :c ;
10 }
11 char s[MAX],t[MAX];
12 short dp[MAX][MAX];    //定义的类型为short
13 
14 int main(){
15     int i,j,n;
16     while(scanf("%d",&n)!=EOF){
17         scanf("%s",s);
18         for(i=0;i<n;i++)
19             t[i] = s[n-i-1];
20         t[n] = 0;
21         memset(dp,0,sizeof(dp));
22         for(i=1;i<=n;i++){
23             for(j=1;j<=n;j++){
24                 if(s[i-1] == t[j-1])
25                     dp[i][j] = dp[i-1][j-1] + 1;
26                 dp[i][j] = max(dp[i][j],dp[i-1][j],dp[i][j-1]);
27             }    
28         }
29         printf("%d\n",n-dp[n][n]);
30     }
31     return 0;
32 }

 

另一种方法:dp[i][j]表示从第i个字符到第j个字符能构成的回文添加的最少字符。
 1 #include <stdio.h>
 2 #define Min(a,b) (a<b?a:b)
 3 const int MAX = 5001;
 4 char ch[MAX];
 5 short dp[MAX][MAX]={0};
 6 int main()
 7 {
 8     int lenth, i, j;
 9     while(scanf("%d%s",&lenth, ch+1)!=EOF)
10     {
11         for(i=lenth;i>0;i--)    //自底向上
12         {    
13             for(j=i+1;j<=lenth;j++)
14             {
15                 if(ch[i]==ch[j]){
16                     dp[i][j] = dp[i+1][j-1];
17                 }
18                 else{
19                     dp[i][j] = Min(dp[i+1][j],dp[i][j-1])+1;
20                 }
21             }
22         }
23         printf("%d\n",dp[1][lenth]);
24     }
25     return 0;
26 }

 可是在某些变态的OJ里,上面的方法仍然不能AC,这是需要引入滚动数组优化空间,比如在第一种方法之上

代码如下:

 1 # include<stdio.h>
 2 # include<string.h>
 3 
 4 #define MAX 5005
 5 
 6 int max(int a,int b,int c){
 7     int temp;
 8     temp = a>b ? a :b;
 9     return temp>c ?temp :c ;
10 }
11 char s[MAX],t[MAX];
12 short dp[2][MAX];
13 
14 int main(){
15     int i,j,n;
16     while(scanf("%d",&n)!=EOF){
17         scanf("%s",s);
18         for(i=0;i<n;i++)
19             t[i] = s[n-i-1];
20         t[n] = 0;
21         memset(dp,0,sizeof(dp));
22         for(i=1;i<=n;i++){
23             for(j=1;j<=n;j++){
24                 if(s[i-1] == t[j-1])
25                     dp[i%2][j] = dp[(i-1)%2][j-1] + 1;
26                 dp[i%2][j] = max(dp[i%2][j],dp[(i-1)%2][j],dp[i%2][j-1]);
27             }    
28         }
29         printf("%d\n",n-dp[n%2][n]);
30     }
31     return 0;
32 }

 



posted @ 2013-08-17 16:48  贾树丙  阅读(247)  评论(0编辑  收藏  举报