您的位置:首页 > 其它

NYOJ 37 回文字符串 (dp)

2012-08-17 19:53 393 查看
地址: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};

代码如下:

#include<stdio.h>
#include<string.h>
#define N 1010
int d

;
char a
;
int min(int x,int y)
{
return x<y?x:y;
}
int main()
{
int i,j,p,n,test;
scanf("%d",&test);
while(test--)
{
scanf("%s",a+1); //这点让我贡献了好几个WA,至于为啥a+1,目前还不太清楚。。。
n=strlen(a+1);
for(i=1;i<=n;i++)
d[i][i]=d[i][i-1]=0;
for(p=1;p<n;p++)
{
for(i=1;i<=n-p;i++)
{
j=i+p;
d[i][j]=10000;
if(a[i]==a[j])
d[i][j]=d[i+1][j-1];
else
{
d[i][j]=min(d[i][j],d[i+1][j]+1);
d[i][j]=min(d[i][j],d[i][j-1]+1);
}
}
}
printf("%d\n",d[1]
);
}
return 0;
}


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

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

原串:12341
反转:14321
结果:1423241
代码如下:

#include<stdio.h>
#include<string.h>
int f[1001][1001];
int main()
{
char str1[1001],str2[1001];
int ncases,i,j,k,len;
scanf("%d",&ncases);
while(ncases--)
{
memset(str1,0,sizeof(str1));
memset(str2,0,sizeof(str2));
scanf("%s",str1);
len=strlen(str1);
for(k=0,i=len-1;i>=0;i--)//**转置字符串**//
{
str2[k++]=str1[i];
}
for(i=0;i<=len;i++)
{
f[i][0]=f[0][i]=0;
}
for(i=1;i<=len;i++)
{
for(j=1;j<=len;j++)
{
if(str1[i-1]==str2[j-1])//**求最长公共子序列**//
{
f[i][j]=f[i-1][j-1]+1;
}
else
{
f[i][j]=f[i-1][j]>f[i][j-1]?f[i-1][j]:f[i][j-1];
}
}
}
printf("%d\n",len-f[len][len]);//**用长度减去最长公共子序列得到需要最少添加的字符数**//
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: