HDu 1513 LCS

来源:互联网 发布:优化相机 编辑:程序博客网 时间:2024/06/05 07:46

Palindrome

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4013    Accepted Submission(s): 1363


Problem Description
A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a program which, given a string, determines the minimal number of characters to be inserted into the string in order to obtain a palindrome.

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
Your program is to read from standard input. The first line contains one integer: the length of the input string N, 3 <= N <= 5000. The second line contains one string with length N. The string is formed from uppercase letters from 'A' to 'Z', lowercase letters from 'a' to 'z' and digits from '0' to '9'. Uppercase and lowercase letters are to be considered distinct.
 

Output
Your program is to write to standard output. The first line contains one integer, which is the desired minimal number.
 

Sample Input
5Ab3bd
 

Sample Output
2
 

Source
IOI 2000
//解题思路,把字符串倒过来,然后找最大的公共子序列,然后用总的减去公共子序列就行了,但是要注意5000*5000的二位数组会超内存的,从网上借鉴了滚动的数组,粘贴原理参考参考,以下粘贴的:
滚动数组 举个简单的例子:
int i,d[100];
d[0]=1;d[1]=1;
for(i=2;i<100;i++)
d[i]=d[i-1]+d[i-2];
printf("%d",d[99]);
上面这个循环d[i]只需要解集中的前2个解d[i-1]和d[i-2];
为了节约空间用滚动数组的方法
 
 
int d[3];
d[0]=1;d[1]=1;
for(i=2;i<100;i++)
d[i%3]=d[(i-1)%3]+d[(i-2)%3];
printf("%d",d[99%3]);
 
 
注意上面的运算,我们只留了最近的3个解,数组好象在“滚动?一样,所以叫滚动数组
 
 
对于二维数组也可以用这种方法 例如:
int i,j,d[100][100];
for(i=1;i<100;i++)
    for(j=0;j<100;j++)
        d[i][j]=d[i-1][j]+d[i][j-1];
 
 
上?的d[i][j]忪便赖于d[i-1][j],d[i][j-1];
迿用滚动数组
int i,,j,d[2][100];
for(i=1;i<100;i++)
    for(j=0;j<100;j++)
        d[i%2][j]=d[(i-1)%2][j]+d[i%2][j-1];
 
 
滚动数组实际是一种节约空间的办法,时间上没什么优势,多用于DP中,举个例子先: 
一个DP,平常如果需要1000×1000的空间,其实根据DP的特点,能以2×1000的空间解决问题,并且通过滚动,获得和1000×1000一样的效果。
 
 
参考代码如下:
 
#include<stdio.h>#include<string.h>#define max(a,b) a>b?a:bchar s1[5005],s2[5005];int dp[2][5005],n;void lcs(){int i,j;memset(dp,0,sizeof(dp));for(i=1;i<=n;i++){     for(j=1;j<=n;j++){     if(s1[i-1]==s2[j-1]){     dp[i%2][j]=dp[(i-1)%2][j-1]+1;         }      else        dp[i%2][j]=max(dp[(i-1)%2][j],dp[i%2][j-1]);       }   } } int main(){   int i,j;   while(~scanf("%d",&n)){       scanf("%s",s1);       for(i=0;i<n;i++)         s2[i]=s1[n-1-i];         s2[i]='\0';         lcs();         printf("%d\n",n-dp[n%2][n]);    } return 0; }

0 0
原创粉丝点击