Codeforces 682D Alyona and Strings(DP)
2016-07-12 09:16
155 查看
题目大概说给两个字符串s和t,然后要求一个包含k个字符串的序列,而这个序列是两个字符串的公共子序列,问这个序列包含的字符串的总长最多是多少。
如果用DP解,考虑到问题的规模,自然这么表示状态:
dp[i][j][k]表示s[0...i]与t[0...j]包含k个字符串的公共子序列的最大总长
想怎么转移时,我发现这样表示状态不好转移,还得加一维:
dp[i][j][k][0]表示s[0...i]与t[0...j]包含k个字符串的公共子序列的最大总长,且s[i]和t[j]不属于序列第k个字符串
dp[i][j][k][1]表示s[0...i]与t[0...j]包含k个字符串的公共子序列的最大总长,且s[i]和t[j]属于序列第k个字符串
转移的话:
dp[i][j][k][1]能转移仅s[i]=t[j],可以通过在s[0...i-1]和t[0...j-1]的后面作为新加的序列字符串转移,即d[i-1][j-1][k-1]+1;也可以不作为新加的序列字符串,与前面的拼接转移,不过仅当s[i-1]=t[j-1],即dp[i-1][j-1][k]+1;
dp[i][j][k][0]就是s[i]、t[j]忽略的情况,从dp[i-1][j][k]、dp[i][j-1][k]和dp[i][j][k]转移
转移感觉很麻烦,写着写着调着调着,终于过了样例,然后直接提交——居然就AC了?简直不敢相信。。
如果用DP解,考虑到问题的规模,自然这么表示状态:
dp[i][j][k]表示s[0...i]与t[0...j]包含k个字符串的公共子序列的最大总长
想怎么转移时,我发现这样表示状态不好转移,还得加一维:
dp[i][j][k][0]表示s[0...i]与t[0...j]包含k个字符串的公共子序列的最大总长,且s[i]和t[j]不属于序列第k个字符串
dp[i][j][k][1]表示s[0...i]与t[0...j]包含k个字符串的公共子序列的最大总长,且s[i]和t[j]属于序列第k个字符串
转移的话:
dp[i][j][k][1]能转移仅s[i]=t[j],可以通过在s[0...i-1]和t[0...j-1]的后面作为新加的序列字符串转移,即d[i-1][j-1][k-1]+1;也可以不作为新加的序列字符串,与前面的拼接转移,不过仅当s[i-1]=t[j-1],即dp[i-1][j-1][k]+1;
dp[i][j][k][0]就是s[i]、t[j]忽略的情况,从dp[i-1][j][k]、dp[i][j-1][k]和dp[i][j][k]转移
转移感觉很麻烦,写着写着调着调着,终于过了样例,然后直接提交——居然就AC了?简直不敢相信。。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int d[1111][1111][11][2]; int main(){ int n,m,K; char s[1111]={0},t[1111]={0}; scanf("%d%d%d",&n,&m,&K); for(int i=0; i<n; ++i){ scanf(" %c",&s[i]); } for(int i=0; i<m; ++i){ scanf(" %c",&t[i]); } memset(d,0,sizeof(d)); if(s[0]==t[0]) d[0][0][1][1]=1; for(int i=0; i<n; ++i){ for(int j=0; j<m; ++j){ if(i==0 && j==0) continue; for(int k=1; k<=K; ++k){ if(i==0){ if(s[i]==t[j]){ d[i][j][1][1]=1; } d[i][j][1][0]=max(d[i][j-1][1][0],d[i][j-1][1][1]); }else if(j==0){ if(s[i]==t[j]){ d[i][j][1][1]=1; } d[i][j][1][0]=max(d[i-1][j][1][0],d[i-1][j][1][1]); }else{ if(s[i]==t[j]){ d[i][j][k][1]=max(d[i-1][j-1][k-1][0],d[i-1][j-1][k-1][1])+1; if(s[i-1]==t[j-1]) d[i][j][k][1]=max(d[i][j][k][1],d[i-1][j-1][k][1]+1); } d[i][j][k][0]=max(d[i-1][j][k][0],d[i][j-1][k][0]); d[i][j][k][0]=max(d[i][j][k][0],d[i][j-1][k][1]); d[i][j][k][0]=max(d[i][j][k][0],d[i-1][j][k][1]); d[i][j][k][0]=max(d[i][j][k][0],d[i-1][j-1][k][0]); if(s[i-1]==t[j-1]) d[i][j][k][0]=max(d[i][j][k][0],d[i-1][j-1][k][1]); } } } } printf("%d",max(d[n-1][m-1][K][0],d[n-1][m-1][K][1])); return 0; }
相关文章推荐
- elasticsearch+filebeat日志分析
- 常用的网址收藏
- Android抽象布局——include、merge 、ViewStub
- 图样图森破 设置虚拟机优先级真的很容易?
- 微信公众号开发教程[004]-消息管理-回复消息
- linux下压缩与解压缩
- 《剑指offer》-孩子们的游戏(圆圈中最后剩下的数)
- 三维重建(四)PMVS算法 the patch-based MVS algorithm
- I/O流
- 微信公众号开发教程[003]-消息管理-接收消息
- Android项目依赖多个项目,它们的jar包冲突的解决办法
- Oracle中异常处理
- 随机数生成器
- ASP.NET Core Linux下为 dotnet 创建守护进程(必备知识)
- PHP数据库表操作的封装类及用法实例详解
- 【OpenCV入门教程之一】 安装OpenCV:OpenCV 3.0、OpenCV 2.4.8、OpenCV 2.4.9 +VS 开发环境配置
- Centos 6.7 图文讲解救援模式修复fstab过程
- 微信公众号开发教程[002]-配置
- 左手定则
- 浅谈Spring事务隔离级别