POJ 1159 Palindrome

题目链接:http://poj.org/problem?id=1159

这道题本质上是求一个子序列和其逆子序列的最长公共子序列(证明略),但是输出的是未匹配的字符数。

数据比较大,5000*5000的数据,开数组肯定MLE,但是不小心用short睡过去了= =!

正解应该是用滚动数组,把数据缩小到2*5000.

因为当前状态之和前一状态有关,所以进行i%2取余就好了。

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;

const int INF=0x3f3f3f3f;
const int maxn=5005;
int T,n;
char s1[maxn],s2[maxn];
int dp[2][maxn];

int main(){
#ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
#endif
    while(~scanf("%d",&n)){
    	scanf("%s",s1);
    	for(int i=0;i<n;i++)
    		s2[i]=s1[n-1-i];
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;i++){
			for(int 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]);
			}
		}
		printf("%d\n",n-dp[n%2][n]);
	}
	return 0;

}


附上short水过去的代码:

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;

const int INF=0x3f3f3f3f;
const int maxn=5005;
int T,n;
char s1[maxn],s2[maxn];
int dp[maxn][maxn];

int main(){
#ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
#endif
    while(~scanf("%d",&n)){
    	scanf("%s",s1);
    	for(int i=0;i<n;i++)
    		s2[i]=s1[n-1-i];
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(s1[i-1]==s2[j-1])
					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;

}


你可能感兴趣的:(POJ 1159 Palindrome)