PalindromeTime Limit:3000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Description
Input
Output
Sample Input
5
Ab3bd
Sample Output
2
题意:给出一个字符串,问最少添加几个字符可以使其变为回文串。
思路:我们分析一下回文串的特点,其逆序串str'与str是相同的,由于题目规定可以在任意的位置添加,那么,当str'与str不同时,我们可以先找出他们相同的部分,对于剩下不同的那部分,我们可以通过一个策略:互补。即把str特有的加到str'中,把str'特有的加到str中,这样一定可以获得一个回文串,怎么做到最少呢?仔细想想,如果不同的字符越少,那索要添加的就越少,即相同的字符越多,所要添加的就越少。因此,这个问题可以转换为一个最长公共子序列问题,该问题一般采用DP方法解决,递推方程是:
代码:
#include <iostream> #include <stdio.h> #include <string.h> #define MAXN 5010 using namespace std; int dp[2][MAXN]; int max(int a,int b) { return a>b?a:b; } int lcs(char *str1,char *str2,int len) { int i,j,e=0; memset(dp,0,sizeof(dp)); for(i=1;i<=len;i++) { e=1-e; for(j=1;j<=len;j++) { if(str1[i]==str2[j]) { dp[e][j]=dp[1-e][j-1]+1; } else { dp[e][j]=max(dp[1-e][j],dp[e][j-1]); } } } return dp[e][len]; } int main() { int len,i,j; char str1[MAXN],str2[MAXN]; while(~scanf("%d",&len)) { scanf("%s",str1+1); str2[len]='\0'; for(i=len,j=1;i>0;i--,j++) str2[i]=str1[j]; //cout<<str1<<endl<<str2<<endl; printf("%d\n",len-lcs(str1,str2,len)); } return 0; }