NYOJ 37 回文字符串 (dp)

地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=37

思路1:dp动态规划

分析:d[i][j]表示从第 i 到第 j 的最优解;if(a[i]==a[j]) d[i][j]=d[i+1][j-1];d[i][j]=max{d[i][j] , d[i+1][j]+1 , d[i][j-1]+1};

代码如下:

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #define N 1010
 4 int d[N][N];
 5 char a[N];
 6 int min(int x,int y)
 7 {
 8     return x<y?x:y;
 9 }
10 int main()
11 {
12     int i,j,p,n,test;
13     scanf("%d",&test);
14     while(test--)
15     {
16         scanf("%s",a+1); //这点让我贡献了好几个WA,至于为啥a+1,目前还不太清楚。。。
17         n=strlen(a+1);
18         for(i=1;i<=n;i++)
19         d[i][i]=d[i][i-1]=0;
20         for(p=1;p<n;p++)
21         {
22             for(i=1;i<=n-p;i++)
23             {
24                 j=i+p;
25                 d[i][j]=10000;
26                 if(a[i]==a[j])  
27                   d[i][j]=d[i+1][j-1];
28                 else
29                 {
30                   d[i][j]=min(d[i][j],d[i+1][j]+1);
31                   d[i][j]=min(d[i][j],d[i][j-1]+1);
32                 }
33             }
34         }
35         printf("%d\n",d[1][n]);
36     }
37     return 0;
38 }
39     

 

思路2:在纸上测试几组数据,发现先逆转原来的字符串,再用原来的字符串跟逆转后的字符串进行比较,求得的最长公共子序列就是回文串,也就是不需要添加的,再用总长度减去最长公共子序列就可以得到最少需要添加的字符数。代码就简单了,以前写过的稍稍改下就直接贴上来了。

本题看起来似乎比较难,但其实如果想出思路就发现,其实可以转化为一个最长公共子序列问题,求出字符串及其反转的最长公共子序列长度,再把反转后的非公共部分填充进原字符串就行了,如下表:

 

原串: 1   2 3   4 1
反转: 1 4   3 2   1
结果: 1 4 2 3 2 4 1

代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 int f[1001][1001];
 4 int main()
 5 {
 6     char str1[1001],str2[1001];
 7     int ncases,i,j,k,len;
 8     scanf("%d",&ncases);
 9     while(ncases--)
10     {
11         memset(str1,0,sizeof(str1));
12         memset(str2,0,sizeof(str2));
13         scanf("%s",str1);
14         len=strlen(str1);
15         for(k=0,i=len-1;i>=0;i--)//**转置字符串**//
16         {
17             str2[k++]=str1[i];
18         }
19         for(i=0;i<=len;i++)
20         {
21             f[i][0]=f[0][i]=0;
22         }
23         for(i=1;i<=len;i++)
24         {
25             for(j=1;j<=len;j++)
26             {
27                 if(str1[i-1]==str2[j-1])//**求最长公共子序列**//
28                 {
29                     f[i][j]=f[i-1][j-1]+1;
30                 }
31                 else
32                 {
33                     f[i][j]=f[i-1][j]>f[i][j-1]?f[i-1][j]:f[i][j-1];  
34                 }
35             }
36         }
37         printf("%d\n",len-f[len][len]);//**用长度减去最长公共子序列得到需要最少添加的字符数**//
38     }
39     return 0;
40 }        

 

posted on 2012-08-17 19:53  mycapple  阅读(468)  评论(0编辑  收藏  举报

导航