P2516 [HAOI2010]最长公共子序列
看到数据范围,显然 $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<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=,mo=1e8;
inline int fk(int x) { return x>=mo ? x-mo : x; }
int n,m,f[][N],g[][N];
char a[N],b[N];
int main()
{
scanf("%s",a+); scanf("%s",b+);
n=strlen(a+)-,m=strlen(b+)-;
for(int i=;i<=m;i++) f[][i]=;
int cur=,pre;
for(int i=;i<=n;i++)
{
pre=cur; cur^=; f[cur][]=;
for(int j=;j<=m;j++) g[cur][j]=f[cur][j]=;
for(int j=;j<=m;j++)
{
if(a[i]==b[j]) g[cur][j]=g[pre][j-]+,f[cur][j]=f[pre][j-]; 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-]>g[cur][j]) g[cur][j]=g[cur][j-],f[cur][j]=f[cur][j-];
else if(g[cur][j-]==g[cur][j]) f[cur][j]=fk(f[cur][j]+f[cur][j-]); if(g[cur][j]==g[pre][j-]) f[cur][j]=fk(f[cur][j]-f[pre][j-]+mo);
}
}
printf("%d\n%d\n",g[cur][m],f[cur][m]);
return ;
}
P2516 [HAOI2010]最长公共子序列的更多相关文章
- 2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组)
2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组) https://www.luogu.com.cn/problem/P2516 题意: 给定字符串 \(S\) ...
- 洛谷P2516 [HAOI2010]最长公共子序列(LCS,最短路)
洛谷题目传送门 一进来就看到一个多月前秒了此题的ysn和YCB%%% 最长公共子序列的\(O(n^2)\)的求解,Dalao们想必都很熟悉了吧!不过蒟蒻突然发现,用网格图貌似可以很轻松地理解这个东东? ...
- 洛谷 P2516 [HAOI2010]最长公共子序列
题目传送门 解题思路: 第一问要求最长公共子序列,直接套模板就好了. 第二问要求数量,ans[i][j]表示第一个字符串前i个字符,第二个字符串前j个字符的最长公共子序列的数量 如果f[i][j]是由 ...
- P2516 [HAOI2010]最长公共子序列 题解(LCS)
题目链接 最长公共子序列 解题思路 第一思路: 1.用\(length[i][j]\)表示\(a\)串的前\(i\)个字符与\(b\)串的前\(j\)个字符重叠的最长子串长度 2.用\(num[i][ ...
- luogu P2516 [HAOI2010]最长公共子序列
传送门 首先那个\(O(n^2)\)的dp都会吧,不会自己找博客或者问别人,或是去做模板题(误) 对以下内容不理解的,强势推荐flash的博客 我们除了原来记录最长上升子序列的\(f_{i,j}\), ...
- 洛谷P2516 [HAOI2010]最长公共子序列
题目描述 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X="x0,x1,-,xm-1",序列Y=& ...
- Luogu P2516 [HAOI2010]最长公共子序列 DP
首先$LIS$显然:$f[i][j]=max(f[i][j-1],f[i-1][j],(a[i]==b[j])*f[i-1][j-1])$ 考虑如何转移数量: 首先,不管$a[i]$是否等于$b[j] ...
- [BZOJ2423][HAOI2010]最长公共子序列
[BZOJ2423][HAOI2010]最长公共子序列 试题描述 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x ...
- 【BZOJ2423】[HAOI2010]最长公共子序列 DP
[BZOJ2423][HAOI2010]最长公共子序列 Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字 ...
随机推荐
- nowcoder 79F 小H和圣诞树 换根 DP + 根号分治
设节点个数大于 $\sqrt n$ 的颜色为关键颜色,那么可以证明关键颜色最多有 $\sqrt n$ 个.对于每个关键颜色,暴力预处理出该颜色到查询中另一个颜色的距离和. 对于不是关键颜色的询问,直接 ...
- [NOIP2017]注意点
1.数据大却没开long long 导致的gg.2.文件读入时stdin打成stdout...3.桶维护数值,有负值要平移,且数值最好稍大(否则可能RE).4.很智障地打错变量.5.DP或其他涉及到转 ...
- 关于win7系统下gitbook的安装与gitbook editor的配合使用
1.安装nodejs 2.node -v,可查看node版本: npm -v,可查看npm版本 3.npm install gitbook-cli -g,安装gitbook 此过程经常报错,如果报错, ...
- HDU 6012 Lotus and Horticulture(离散化)
题目代号:HDU 6012 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6012 Lotus and Horticulture Time Limit: ...
- js的浅拷贝和深拷贝和应用场景
为什么会用到浅拷贝和深拷贝 首先来看一下如下代码 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e ...
- Linux shell - cut命令用法(转载)
cut [-bn] [file] 或 cut [-c] [file] 或 cut [-df] [file] 使用说明 cut 命令从文件的每一行剪切字节.字符和字段并将这些字节.字符和字段写至标 ...
- Oracle开发:normal ,sysdba,sysoper区别
Oracle将用户分成两类:[system]和[sys] [system]用户只能用normal身份登陆em.(可以看成公司的普通成员) [sys]用户具有“SYSDBA”(可以看成公司的CEO)或者 ...
- controller大全(推荐)
@Controller @RequestMapping("/router") @SessionAttributes(value = { "username" } ...
- Mybatis 一对多 关联查询查询
一对多 与 一对一 查询有许多相似之处. 最主要的区别是 查询结果是list,与之对应的标签为collection. 班级和学生,一个班有多个学生,而每个学生只能属于一个班. 此时班级编号作为学生表的 ...
- sklearn—无监督最近邻
无监督最近邻 NearestNeighbors (最近邻)实现了 unsupervised nearest neighbors learning(无监督的最近邻学习). 它为三种不同的最近邻算法提供统 ...