poj 1159 Palindrome (反串LCS 与 DP两种方法)
题目链接http://poj.org/problem?id=1159
LCS之前只写了一次,反串了以后都没有反应过来可以用LCS。。。
给出反串LCS代码:
//反串LCS #include<iostream> #include<cstring> #include<cmath> using namespace std; int n; char s[5005]; char rs[5005]; int dp[2][5005];///滚动数组 int lcs(char* str1,char* str2){ memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(str1[i-1]==str2[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]); } return dp[n%2][n]; } int main(){ while(cin>>n>>s){ int i; for(i=0;i<n;i++) rs[i]=s[n-i-1]; rs[i]='\0'; cout<<n-lcs(s,rs)<<endl; } return 0; }
但是据说有动态规划的做法,就沿着动态规划的思路想了想,发现其实很简单
给出基本DP做法
/* 动态规划思想 我们先从上至下的分析 以题目数据做例子 假如字符串Ab3bd已经找到最优的最少插入方法,设为dp(Ab3bd) 那么,我们想得出b3bd的最优解 因为A与b3bd的最后一个字符d不相同,说明排除A以后,就可以省掉一个插入,则dp(b3bd)=dp(Ab3bd)-1 同理,dp(Ab3b)=dp(Ab3bd)-1 如果把字符串改成 Ab3bdA 那么dp(b3bdA)=dp(Ab3bd)=dp(Ab3bdA)+1 我们就发现了关系 if(i==j) dp(i....j)=dp(i+1...j)-1 //此时dp(i+1....j)==dp(i....j-1) else dp(i....j)=min( dp(i+1....j)+1,dp(i....j-1)+1 )//此时dp(i+1...j)!=dp(i...j-1) 实现: 设dp[i][j]为从i到j的最优解 可以看出,在求dp[i][j]时,dp[i+1][j]和dp[i][j-1]就已经要求出来了 所以有i递减,j递增的顺序(显然i从n递减,j从i递增) 答案就是 dp[1][n] 算法时间O(n^2) */ #include<iostream> #include<cstring> #include<cmath> using namespace std; int n; char s[5005]; int dp[2][5005]; int main (){ while(cin>>n>>s){ memset(dp,0,sizeof(dp));//dp[i][i]=0 for(int i=n-1;i>=1;i--) for(int j=i+1;j<=n;j++) { if(s[i-1]==s[j-1]) dp[i&1][j]=dp[(i+1)&1][j]-1; else dp[i&1][j]=min(dp[(i+1)&1][j],dp[i&1][j-1])+1; } cout<<dp[1][n]<<endl; } return 0; }
其实后来发现s[i-1]==s[j-1]时,dp[i][j]=dp[i+1][j-1]。。。貌似好一点