Palindrome
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 52560 | Accepted: 18119 |
Description
As an example, by inserting 2 characters, the string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "Adb3bdA"). However, inserting fewer than 2 characters does not produce a palindrome.
Input
Output
Sample Input
5 Ab3bd
Sample Output
2
题意:回文词是一种对称的字符串。把任意给定一个字符串用最少的步骤数,通过插入若干字符,都可以变成回文词。比如 “Ab3bd”插入2个字符后可以变成回文词“dAb3bAd”或“Adb3bdA”,但是插入少于2个的字符无法变成回文词。
;
方法一:倒序后比较,求出最长子序列,然后在用长度减去最长子序列的值即为改变的值;
代码如下:
#include<cstdio>
#include<cstring>
#define max(a,b) (a>b?a:b)
char str[5050],str1[5050];
short c[5050][5050];
int main()
{
int i,j,n;
while(scanf("%d",&n)!=EOF)
{
getchar();
memset(c,0,sizeof(c));
memset(str,0,sizeof(str));
memset(str1,0,sizeof(str1));
for(i=1;i<=n;i++)
scanf("%c",&str[i]);
for(j=1,i=n;i>0;i--)
str1[j++]=str[i];
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==0||j==0)
c[i][j]= 0;
else if(str[i]==str1[j])
c[i][j]=c[i-1][j-1]+1;
else if(str[i]!=str1[j])
c[i][j]=max(c[i][j-1],c[i-1][j]) ;
}
printf("%d\n",n-c[n][n]);
}
return 0;
}
方法二:
令c(i,j)表示将子串aia(i+1)…aj变成回文词的最小添加字符数。则这此问题就是要求c(1,n)。
先来看看求c(1,10),
一。如果a1= a10则c(1,10) =c(2,9);
二。如果a1!= a10则将a1…a10变成回文词无非只有两种情况:
1.先将 a1…a9变成回文词,再在两头加上a10;
2.先将 a2…a10变成回文词,再在两头加上a1;
即c(1,10) =c(1,9)+1或c(1,10) =c(2,10)+1.
综合一和二,则变成了求三个c(1,9),c(2,10),c(2,9),如此类推:求c(1,8),c(2,9),c(2,8) ;c(2,9),c(3,10),c(3,9) ;c(2,8),c(3,9),c(3,8).。。。。。
c(i,j)满足如下递推关系:
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
short dp[5050][5050];//注意用short类型,不然会超空间;
char str[5050];
int main()
{
int n,i,j,k;
memset(dp,0,sizeof(dp));
memset(str,0,sizeof(str));
while(scanf("%d",&n)!=EOF)
{
scanf("%s",str+1);
//getchar();
for(i=1;i<n;i++)
{
for(k=1;i+k<=n;k++)
{
j=i+k;
if(str[k]==str[j])
{
dp[k][j]=dp[k+1][j-1];
}
else
{
dp[k][j]=min(dp[k][j-1]+1,dp[k+1][j]+1);
}
}
}
printf("%d\n",dp[1][n]);
}
return 0;
}