您的位置:首页 > 其它

1159Palindrome之求最大子序列dp

2013-10-01 21:24 323 查看
Palindrome
Time Limit: 3000MSMemory Limit: 65536K
Total Submissions: 48933Accepted: 16817
DescriptionA 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 orderto 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.InputYour 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 lettersfrom 'a' to 'z' and digits from '0' to '9'. Uppercase and lowercase letters are to be considered distinct.OutputYour program is to write to standard output. The first line contains one integer, which is the desired minimal number.Sample Input
5
Ab3bd
Sample Output
2
#include<iostream>
using namespace std;
#define NUMMAX 5001
short int getLCS(char s1[],char s2[],int len1,int len2);
short int dp[NUMMAX][NUMMAX];
int main(){
int N;
cin>>N;
char s1[NUMMAX],s2[NUMMAX];
for(int i=1;i<=N;i++){
cin>>s1[i];
s2[N-i+1]=s1[i];
}
cout<<N-getLCS(s1,s2,N,N);
system("pause");
}
short int max(int a,int b){
return a>b?a:b;
}
short int getLCS(char s1[],char s2[],int len1,int len2){
for(int i=0;i<=len2;i++)
dp[0][i]=0;
for(int i=0;i<=len1;i++)
dp[i][0]=0;
for(int i=1;i<=len1;i++){
for(int j=1;j<=len2;j++){
if(s1[i]==s2[j]){
dp[i][j]=max((dp[i-1][j-1]+1),dp[i][j]);
}else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[len1][len2];
}
解题报告copy之:
 

poj-1159-Palindrome-学习滚动数组

分类: POJ2013-01-26 09:14 340人阅读 评论(0) 收藏 举报题意:给你一串字符串,让你求最少加入几个字符,才能使得这个字符串是个回文串。做法:设a[i]是这个字符串,b[i]是这个字符串的逆序串。那么a[i],b[i]的最长公共子序列就是所求的字符串里拥有的最大的回文串。然后用总串长减去最大的回文串长度即为所求。求最长公共子序列的公式为:dp[i][j]=max(dp[i-1] [j],dp[i][j-1])if(a[i]==b[i])dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);如果直接求的话,势必要开一个5001*5001的数组,铁定MLE。有一下两种解决方法:1,开short int型数组这是poj返回的结果:2,运用动态数组。根据dp滚动的过程我们可以知道,dp【i】【j】的值不会与dp[i-2][0.....n]的值有关系。那么可以把dp[i][j]的值覆盖到dp[i-2][j]上。即dp[i][j]为dp[i%2][j];poj返回的结果:对比以上两种方法,显而易见的可以得出2的方法很节约空间,就是耗时略长。1,short int数组[html] view plaincopy#include<iostream>#include<stdio.h>#include<string.h>#define max(a,b) (a>b?a:b)using namespace std;short int dp[5001][5001];int main(){int a[5001];int b[5001];int i,j;int n;char str;cin>>n;getchar();for(i=1;i<=n;i++){scanf("%c",&str);a[i]=str;b[n-i+1]=str;}for(i=0;i<=n;i++){dp[i][0]=0;dp[0][i]=0;}for(i=1;i<=n;i++){for(j=1;j<=n;j++){dp[i][j]=max(dp[i][j-1],dp[i-1][j]);if(a[i]==b[j]){dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);}}}int len;len=dp;printf("%d\n",n-len);return 0;}2,滚动数组[html] view plaincopy#include<iostream>#include<stdio.h>#include<string.h>using namespace std;int main(){int a[5001];int b[5001];int dp[10][5001];int i,j;int n;char str;cin>>n;getchar();for(i=1;i<=n;i++){scanf("%c",&str);a[i]=str;b[n-i+1]=str;}dp[1][0]=dp[0][0]=0;for(i=0;i<=n;i++){dp[0][i]=0;}for(i=1;i<=n;i++){for(j=1;j<=n;j++){dp[i%2][j]=max(dp[i%2][j-1],dp[(i-1)%2][j]);if(a[i]==b[j]){dp[i%2][j]=max(dp[i%2][j],dp[(i-1)%2][j-1]+1);}}}int len;len=dp[n%2];printf("%d\n",n-len);return 0;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: