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 }        

 

你可能感兴趣的:(字符串)