hdu1513Palindrome回文数【LCS】【滚动数组】

来源:互联网 发布:pl sql developer查询 编辑:程序博客网 时间:2024/06/05 23:04

Palindrome

Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 73   Accepted Submission(s) : 20
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
【题意】:给出一个字符串,问将这个字符串变成回文字符串要添加最少几个字符
【分析】:将字符串与其反字符串求一次LCS,然后用n减去公共字符串的长度就是最少要插入的字符个数,但本题中字符串最长有5000,
dp二维数组都开5000的话会超内存,这里就要用到滚动数组,因为在LCS的计算中,i的变换只相差1,所以可以通过对2取余来进行滚动。
【代码】
#include<stdio.h>#include<string.h>#define max(a,b) (a>b?a:b)#define size 5010int n,dp[2][size];char a[size],b[size];int main(){int i,j,k,l,m;while(scanf("%d",&n)!=EOF){memset(dp,0,sizeof(dp));scanf("%s",&a);for(i=0;i<n;i++)b[i]=a[n-1-i];b[i]='\0';for(i=1;i<=n;i++){for(j=1;j<=n;j++){if(a[i-1]==b[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]);}}printf("%d\n",n-dp[n%2][n]);}return 0;}
 
 
关于滚动数组:
滚动数组很适合用在二维DP而且是数组在很大时,可以节省内存,消除超内存的隐患!具体思想还是看了网上的资料,转载一个,共同享用吧!
滚动数组 举个简单的例子:
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一样的效果。

0 0
原创粉丝点击