[HAOI2010]最长公共子序列(LCS+dp计数)
字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij = yj。例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。对给定的两个字符序列,求出他们最长的公共子序列长度,以及最长公共子序列个数。
Solution
这题其实就是让求两个序列的LCS和方案数。
LCS的求法:
dp[i][j]=dp[i-1][j-1]+1(s[i]==s[j])
dp[i][j]=max(dp[i][j-1],dp[i-1][j])(s[i]!=s[j])
这个非常简单,但计数部分需要一些思考。
第一种情况时,我们当前的方案数位不管i位和j位的方案数(因为i和j匹配了),所以要把g[i-1][j]和g[i][j-1]讨论一下。
第二种情况,当dp[i-1][j]==dp[i][j-1]时,我们的g[i-1][j-1]的方案都被算了一次,所以要减掉。
这道题可以加深对LCS的理解。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 5004
#define mod 100000000
using namespace std;
int dp[][N],n1,n2,now;
long long g[][N];
char s1[N],s2[N];
int main(){
scanf("%s%s",s1+,s2+);
n1=strlen(s1+)-;
n2=strlen(s2+)-;
for(int i=;i<=n1;++i)g[][i]=g[][i]=;
for(int i=;i<=n1;++i){
now^=;
for(int j=;j<=n2;++j){
int f=(s1[i]==s2[j]);
if(f){
dp[now][j]=dp[now^][j-]+f;
g[now][j]=g[now^][j-];
if(dp[now^][j]==dp[now][j])(g[now][j]+=g[now^][j])%=mod;
if(dp[now][j-]==dp[now][j])(g[now][j]+=g[now][j-])%=mod;
}
else{
g[now][j]=;
dp[now][j]=max(dp[now^][j],dp[now][j-]);
if(dp[now^][j]==dp[now][j])(g[now][j]+=g[now^][j])%=mod;
if(dp[now][j-]==dp[now][j])(g[now][j]+=g[now][j-])%=mod;
if(dp[now^][j-]==dp[now][j])(g[now][j]-=g[now^][j-])%=mod;
g[now][j]=(g[now][j]+mod)%mod;
}
}
}
printf("%d\n%d",dp[now][n2],g[now][n2]);
return ;
}
[HAOI2010]最长公共子序列(LCS+dp计数)的更多相关文章
- bzoj 2423: [HAOI2010]最长公共子序列【dp+计数】
设f[i][j]为a序列前i个字符和b序列前j个字符的最长公共子序列,转移很好说就是f[i][j]=max(f[i-1][j],f[i][j-1],f[i-1][j-1]+(a[i]==b[j])) ...
- 【BZOJ2423】[HAOI2010]最长公共子序列 DP
[BZOJ2423][HAOI2010]最长公共子序列 Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字 ...
- [BZOJ2423][HAOI2010]最长公共子序列
[BZOJ2423][HAOI2010]最长公共子序列 试题描述 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x ...
- 2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组)
2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组) https://www.luogu.com.cn/problem/P2516 题意: 给定字符串 \(S\) ...
- 1006 最长公共子序列Lcs
1006 最长公共子序列Lcs 基准时间限制:1 秒 空间限制:131072 KB 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdks ...
- 动态规划之最长公共子序列LCS(Longest Common Subsequence)
一.问题描述 由于最长公共子序列LCS是一个比较经典的问题,主要是采用动态规划(DP)算法去实现,理论方面的讲述也非常详尽,本文重点是程序的实现部分,所以理论方面的解释主要看这篇博客:http://b ...
- 编程算法 - 最长公共子序列(LCS) 代码(C)
最长公共子序列(LCS) 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 给定两个字符串s,t, 求出这两个字符串最长的公共子序列的长度. 字符 ...
- C++版 - Lintcode 77-Longest Common Subsequence最长公共子序列(LCS) - 题解
版权声明:本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C++版 - L ...
- POJ 1458 Common Subsequence(最长公共子序列LCS)
POJ1458 Common Subsequence(最长公共子序列LCS) http://poj.org/problem?id=1458 题意: 给你两个字符串, 要你求出两个字符串的最长公共子序列 ...
- 51Nod 1006:最长公共子序列Lcs(打印LCS)
1006 最长公共子序列Lcs 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). ...
随机推荐
- MySQL的binlog及关闭方法
如何关闭MySQL日志,删除mysql-bin.0000*日志文件 - VPS侦探https://www.vpser.net/manage/delete-mysql-mysql-bin-0000-lo ...
- Jenkins Installing and migration
JAVA_Zookeeper_hadoop - CSDN博客https://blog.csdn.net/wangmuming Installing Jenkins on Red Hat distrib ...
- python安装与使用(Windows)
日常使用PHP开发较多,但是有些地方PHP的语言的瓶颈就显露出来了,例如,同样是抓取一个网站的内容,使用PHP需要较为复杂的正则匹配,效率较为低下.python具有丰富的类库,拿过来直接可以使用,功能 ...
- 手机移动端input date placehoder不显示
要解决这个问题,我们可以伪造一个placehoder,通过css跟js来解决这个问题. 为什么要用js的原因是因为当你选择了时间之后,placehoder的文字没有清除掉,所以我们就需要把这个伪造的p ...
- SQLServer数据库分页
以 项目表 PM_Project 为例. PM_Project 全部内容如下(共6条数据): 一.Top – Not In - Top 方式分页 直接的,原始的,不采用函数,纯手动挡. 分步探索过 ...
- 1 Servlet 简介
1 Servlet是sun公司提供的一门用于开发动态web资源的技术.用户若用Java技术开发一个动态web资源或者网页,需要完成以下2个步骤:① 编写一个Java类,实现servlet接口② 把开发 ...
- mysql将视图数据迁移到表中
#字段必须完全一样 INSERT into table1(所有字段) select * from data.视图
- Windows 10 安装PHP Manager 失败的解决办法
首先安装.NET 2.0和.NET 3.5, 在 控制面板----程序----启用或关闭Windows功能 里面 然后修改注册表:HKLM/System/CCS/Services/W3SVC/P ...
- GA-H61M-DS2 BIOS SETTING
Boot Option #1,UEFI:Sandisk SDSSDHP128G Boot Option #2, Boot Option #3, Boot Option #4, Bootup Numbe ...
- Vivado安装、生成bit文件及烧录FPGA的简要流程
https://wenku.baidu.com/view/0294cbb3bb4cf7ec4bfed01a.html