Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 56150 | Accepted: 19398 |
Description
Input
Output
Sample Input
5 Ab3bd
Sample Output
2
给一个字符串,计算最少加多少个字符能够使字符串变成回文串(即从前往后读与从后往前读一样)。
有2种思路,一种是直接区间DP,dp[j][i]表示[i,j]这个子串要变成回文串需要添加多少个字符,状态转移方程如下:另外,这道题还会限制内存。如果定义一个5000*5000的数组会Memory Limit Exceeded。有两种解决方案,一是把数组定义成short型,这样原本的内存会减少很大一部分,大概会在50000kb左右,刚好能够AC;另一种解决方案:因为计算第i行时只需要知道第i-1行,所以可以开一个2*5000的滚动dp数组,这种方法比较推荐,非常节省内存。
/* LCS+short Memory: 49688 KB Time: 1094 MS Language: G++ Result: Accepted */ #include<stack> #include<queue> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #pragma commment(linker,"/STACK: 102400000 102400000") #define lson a,b,l,mid,cur<<1 #define rson a,b,mid+1,r,cur<<1|1 using namespace std; const double eps=1e-6; const int MAXN=5001; char s[MAXN],t[MAXN]; int n,ans,tlen; short int dp[MAXN][MAXN]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE while(scanf("%d",&n)!=EOF) { scanf("%s",s+1); for(int i=n;i>=1;i--) t[n-i+1]=s[i]; t[n+1]=0; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(s[i]==t[j]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); printf("%d\n",n-dp[n][n]); } return 0; }
/* DP+short Memory: 55716 KB Time: 1454 MS Language: G++ Result: Accepted */ #include<stack> #include<queue> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #pragma commment(linker,"/STACK: 102400000 102400000") #define lson a,b,l,mid,cur<<1 #define rson a,b,mid+1,r,cur<<1|1 using namespace std; const double eps=1e-6; const int MAXN=5300; char s[MAXN]; short int n,dp[MAXN][MAXN]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE while(scanf("%d",&n)!=EOF) { scanf("%s",s); memset(dp,0,sizeof(dp)); for(int i=1;i<n;i++) for(int j=i-1;j>=0;j--) { if(s[i]==s[j]) dp[j][i]=dp[j+1][i-1]; else dp[j][i]=(short int)(min(dp[j+1][i],dp[j][i-1])+1); } printf("%d\n",dp[0][n-1]); } return 0; }
/* LCS+滚动数组 Memory: 728 KB Time: 735 MS Language: G++ Result: Accepted */ #include<stack> #include<queue> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #pragma commment(linker,"/STACK: 102400000 102400000") #define lson a,b,l,mid,cur<<1 #define rson a,b,mid+1,r,cur<<1|1 using namespace std; const double eps=1e-6; const int MAXN=5001; char s[MAXN],t[MAXN]; int n,ans,tlen,dp[2][MAXN]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE while(scanf("%d",&n)!=EOF) { scanf("%s",s+1); for(int i=n; i>=1; i--) t[n-i+1]=s[i]; t[n+1]=0; memset(dp,0,sizeof(dp)); int indexs=0; for(int i=1; i<=n; i++) { indexs=!indexs; for(int j=1; j<=n; j++) if(s[i]==t[j]) dp[indexs][j]=dp[!indexs][j-1]+1; else dp[indexs][j]=max(dp[!indexs][j],dp[indexs][j-1]); } printf("%d\n",n-dp[indexs][n]); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
POJ 1159 Palindrome(区间DP/最长公共子序列+滚动数组)
原文地址:http://blog.csdn.net/noooooorth/article/details/47074667