poj 1159 Palindrome 动态规划的三种解法
2016-03-07 13:51
441 查看
最长回文子串→最长公共子序列
补成最短回文串 等价于 先找出最长回文子串长度,之后再匹配那些没有算入最长回文子串的字符。答案=原字符串长度-最长回文子串长度
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; const int INF =0x3f3f3f3f; const int maxn= 5000 ; string a,b; int n; int dp[2][maxn+5]; int main() { while(~scanf("%d",&n)) { cin>>a; b=a; reverse(b.begin(),b.end()); a=" "+a; b=" "+b; int now=0; int pre=1; memset(dp[now],0,sizeof dp[now]); for(int i=1;i<=n;i++) { now^=1; pre^=1; dp[now][0]=0; for(int j=1;j<=n;j++) { if(a[i]==b[j]) dp[now][j]=dp[pre][j-1]+1; else { dp[now][j]=max(dp[now][j-1],dp[pre][j]); } } for(int j=0;j<=n;j++) { dp[pre][j]=dp[now][j]; } } printf("%d\n",n-dp[now] ); } return 0; }
最长回文子串->dp[le][ri]:区间[le,ri]的最长回文子串长度
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; const int INF =0x3f3f3f3f; const int maxn= 5000 ; string a; int n; int dp[3][maxn+5]; int main() { while(~scanf("%d",&n)) { cin>>a; a=" "+a; int now=2,pre=1,prepre=0; for(int le=1;le<=n;le++) { dp[2][le]=1; } memset(dp[1],0,sizeof dp[1]); for(int add=1;add<n;add++) { now=(now+1)%3; pre=(pre+1)%3; prepre=(prepre+1)%3; for(int le=1;le+add<=n;le++) { int ri=le+add; dp[now][le]=0; if(a[le]==a[ri]) { dp[now][le]=dp[prepre][le+1]+2; } else { dp[now][le]=max(dp[now][le],dp[pre][le]); dp[now][le]=max(dp[now][le],dp[pre][le+1]); } } } printf("%d\n",n-dp[now][1]); } return 0; }
dp[le][ri]:区间[le,ri]最少需要添加多少字符
1.未用滚动数组,会超内存
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; const int INF =0x3f3f3f3f; const int maxn= 5000 ; int n; char s[maxn+10]; int dp[maxn+5][maxn+5]; int main() { while(~scanf("%d",&n)) { scanf("%s",s+1); for(int i=1;i<=n;i++) { dp[i][i]=0; dp[i][i-1]=0; } dp[n+1] =0; for(int add=1;add<n;add++) { for(int le=1;le+add<=n;le++) { int ri=le+add; dp[le][ri]=add+1; if(s[le]==s[ri]) dp[le][ri]=min(dp[le][ri],dp[le+1][ri-1]); dp[le][ri]=min(dp[le][ri],dp[le+1][ri]+1 ); dp[le][ri]=min(dp[le][ri],dp[le][ri-1]+1 ); } } printf("%d\n",dp[1] ); } return 0; }
2.滚动数组
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; const int INF =0x3f3f3f3f; const int maxn= 5000 ; int n; char s[maxn+10]; int dp[3][maxn+5]; int main() { while(~scanf("%d",&n)) { scanf("%s",s+1); memset(dp,0,sizeof dp); int now=2,pre=1,prepre=0; for(int add=1;add<n;add++) { now= (now+1)%3; pre= (pre+1)%3; prepre= (prepre+1)%3; for(int le=1;le+add<=n;le++) { int ri=le+add; dp[now][le]=add+1; if(s[le]==s[ri]) dp[now][le]=min(dp[now ][le],dp[ prepre ][le+1]); dp[now][le]=min(dp[now][le],dp[pre][le+1]+1 ); dp[now][le]=min(dp[now][le],dp[pre][le]+1 ); } } printf("%d\n",dp[now][1]); } return 0; }
相关文章推荐
- Android应用架构之MVP实现
- Java异常体系结构
- javax.persistence.NonUniqueResultException: result returns more than one elements
- Hadoop op 1)
- 安全卫士第八天笔记
- 如何识别页面加载过程中出现的元素
- Block
- 使用C#向ACCESS中插入数据
- 使用RxBinding处理控件异步调用
- xamarin.forms 版本自动更新(针对android)
- hosts google
- MyBatis的学习总结六:Mybatis的缓存【参考】
- ZOJ3329
- oracle 新建表空间、用户
- Java实现冒泡排序算法
- Leetcode 1. Two Sum & 15. 3Sum & 16. 3Sum Closest & 18. 4Sum
- 界面传值
- 另类vs2015+xamarin 的android界面乱码 解决
- JS中多种方式创建对象
- Mysql常用语句