博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P2516 [HAOI2010]最长公共子序列
阅读量:4693 次
发布时间:2019-06-09

本文共 2017 字,大约阅读时间需要 6 分钟。

看到数据范围,显然 $n^2$ 的 $dp$...

设 $f[i][j]$ 表示 $A$ 串考虑了前 $i$ 位,$B$ 串考虑了前 $j$ 位,最优情况下的方案数

但是好像没法判断转移来的是否为最优方案?

所以再设 $g[i][j]$ 表示 $A$ 串考虑了前 $i$ 位,$B$ 串考虑了前 $j$ 位,最优情况下的匹配数

那么对于 $g$ 有转移,$g[i][j]=max(g[i-1][j],g[i][j-1])$,如果 $A[i]==B[j]$,那么 $g[i][j]=max(g[i][j],g[i-1][j-1]+1)$

然后考虑 $f$ 的转移

如果 $g[i-1][j]==g[i][j]$ 则 $f[i][j]+=f[i-1][j]$,如果 $g[i][j-1]==g[i][j]$ 则 $f[i][j]+=f[i][j-1]$,如果 $A[i]==B[j]$ 并且 $g[i][j]==g[i-1][j-1]$ 那么 $f[i][j]+=g[i-1][j-1]$

发现输出比答案大...

仔细分析发现如果 $g[i-1][j-1]==g[i][j]$,那么 $f[i-1][j-1]$ 的贡献会分别通过 $f[i][j-1],f[i-1][j]$ 转移到 $f[i][j]$ ,就被算了两次

所以如果 $g[i-1][j-1]==g[i][j]$ ,$f[i][j]$ 还要再减去 $f[i-1][j-1]$

最后,一定要滚动数组

#include
#include
#include
#include
#include
using namespace std;typedef long long ll;inline int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f;}const int N=5007,mo=1e8;inline int fk(int x) { return x>=mo ? x-mo : x; }int n,m,f[2][N],g[2][N];char a[N],b[N];int main(){ scanf("%s",a+1); scanf("%s",b+1); n=strlen(a+1)-1,m=strlen(b+1)-1; for(int i=0;i<=m;i++) f[0][i]=1; int cur=0,pre; for(int i=1;i<=n;i++) { pre=cur; cur^=1; f[cur][0]=1; for(int j=1;j<=m;j++) g[cur][j]=f[cur][j]=0; for(int j=1;j<=m;j++) { if(a[i]==b[j]) g[cur][j]=g[pre][j-1]+1,f[cur][j]=f[pre][j-1]; if(g[pre][j]>g[cur][j]) g[cur][j]=g[pre][j],f[cur][j]=f[pre][j]; else if(g[pre][j]==g[cur][j]) f[cur][j]=fk(f[cur][j]+f[pre][j]); if(g[cur][j-1]>g[cur][j]) g[cur][j]=g[cur][j-1],f[cur][j]=f[cur][j-1]; else if(g[cur][j-1]==g[cur][j]) f[cur][j]=fk(f[cur][j]+f[cur][j-1]); if(g[cur][j]==g[pre][j-1]) f[cur][j]=fk(f[cur][j]-f[pre][j-1]+mo); } } printf("%d\n%d\n",g[cur][m],f[cur][m]); return 0;}

 

转载于:https://www.cnblogs.com/LLTYYC/p/11475700.html

你可能感兴趣的文章
CodeForces 1B
查看>>
win10应用UserControl
查看>>
Magento开发文档(二):Magento配置
查看>>
用递归的方法,判断某个字符串是否为回文
查看>>
[LeetCode] 100. Same Tree Java
查看>>
BZOJ4516: [Sdoi2016]生成魔咒(后缀自动机)
查看>>
查看手机已经记住的WIFI密码
查看>>
Linux实战教学笔记24:SSH连接原理及ssh-key
查看>>
最新版IntelliJ IDEA2019 破解教程(2019.08.07-情人节更新)
查看>>
Dynamic CRM 2013学习笔记(四十二)流程5 - 实时/同步工作流(Workflow)用法图解...
查看>>
Windows下命令(bat可用)
查看>>
我是怎么用缠论在商品里边抢钱之二 (2019-07-12 15:10:10)
查看>>
python入门之正则表达式
查看>>
SAS学习经验总结分享:篇五-过程步的应用
查看>>
Android创建文件夹及文件并写入数据
查看>>
file的getPath getAbsolutePath和getCanonicalPath的不同
查看>>
课时4—切入切出动画
查看>>
eclipse 编辑 python 中文乱码的解决方案
查看>>
Python 爬虫的集中简单方式
查看>>
数据库MySQL/mariadb知识点——触发器
查看>>