题目链接: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; }