[BZOJ2423][HAOI2010]最长公共子序列

试题描述

字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列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的一个子序列。对给定的两个字符序列,求出他们最长的公共子序列长度,以及最长公共子序列个数。

输入

第1行为第1个字符序列,都是大写字母组成,以”.”结束。长度小于5000。

第2行为第2个字符序列,都是大写字母组成,以”.”结束,长度小于5000。

输出

第1行输出上述两个最长公共子序列的长度。

第2行输出所有可能出现的最长公共子序列个数,答案可能很大,只要将答案对100,000,000求余即可。

输入示例

ABCBDAB.
BACBBD.

输出示例


数据规模及约定

见“输入”

题解

第一问是最裸的最长公共子序列dp;第二问须在第一问基础上加一个计数问题,设 f(i, j) 是第一个串到第 i 位,第二个串到第 j 位的最长公共子序列长度,g(i, j) 为 f(i, j) 取最大值时的方案数,那么只要保证上一步转移前也是最优的情况就可以了,注意减去重复的计数。

记得开滚动数组!

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 5010
#define MOD 100000000
char A[maxn], B[maxn], cur;
int f[2][maxn], g[2][maxn]; int main() {
scanf("%s%s", A + 1, B + 1);
int na = strlen(A + 1), nb = strlen(B + 1);
A[na--] = '\0'; B[nb--] = '\0'; for(int i = 1; i <= nb; i++) g[0][i] = 1; g[0][0] = g[1][0] = 1;
for(int i = 1; i <= na; i++) {
cur ^= 1;
for(int j = 1; j <= nb; j++) {
f[cur][j] = max(f[cur^1][j], f[cur][j-1]);
if(A[i] == B[j]) f[cur][j] = max(f[cur][j], f[cur^1][j-1] + 1);
g[cur][j] = 0;
if(f[cur][j] == f[cur^1][j]) g[cur][j] += g[cur^1][j];
if(f[cur][j] == f[cur][j-1]) g[cur][j] += g[cur][j-1];
if(f[cur][j] == f[cur^1][j] && f[cur][j] == f[cur][j-1] && f[cur^1][j-1] == f[cur][j]) g[cur][j] -= g[cur^1][j-1];
if(A[i] == B[j] && f[cur][j] == f[cur^1][j-1] + 1) g[cur][j] += g[cur^1][j-1];
if(g[cur][j] > MOD) g[cur][j] %= MOD;
if(g[cur][j] < 0) g[cur][j] = (g[cur][j] % MOD) + MOD;
// printf("%d %d: %d %d\n", i, j, f[cur][j], g[cur][j]);
}
} printf("%d\n%d\n", f[cur][nb], g[cur][nb]); return 0;
}

[BZOJ2423][HAOI2010]最长公共子序列的更多相关文章

  1. BZOJ2423 HAOI2010最长公共子序列(动态规划)

    大讨论.注意去重. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib& ...

  2. 【BZOJ2423】[HAOI2010]最长公共子序列 DP

    [BZOJ2423][HAOI2010]最长公共子序列 Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字 ...

  3. 【BZOJ2423】最长公共子序列(动态规划)

    [BZOJ2423]最长公共子序列(动态规划) 题面 BZOJ 洛谷 题解 今天考试的时候,神仙出题人\(fdf\)把这道题目作为一个二合一出了出来,我除了orz还是只会orz. 对于如何\(O(n^ ...

  4. 2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组)

    2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组) https://www.luogu.com.cn/problem/P2516 题意: 给定字符串 \(S\) ...

  5. 【bzoj2423】最长公共子序列[HAOI2010](dp)

    题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2423 题目大意:求两个字符串的最长公共子序列长度和最长公共子序列个数. 这道题的话,对于 ...

  6. bzoj:2423: [HAOI2010]最长公共子序列

    Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0, ...

  7. [HAOI2010]最长公共子序列(LCS+dp计数)

    字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X ...

  8. 洛谷P2516 [HAOI2010]最长公共子序列(LCS,最短路)

    洛谷题目传送门 一进来就看到一个多月前秒了此题的ysn和YCB%%% 最长公共子序列的\(O(n^2)\)的求解,Dalao们想必都很熟悉了吧!不过蒟蒻突然发现,用网格图貌似可以很轻松地理解这个东东? ...

  9. LG2516 【[HAOI2010]最长公共子序列】

    前言 感觉这几篇仅有的题解都没说清楚,并且有些还是错的,我再发一篇吧. 分析 首先lcs(最长公共子序列)肯定是板子.但这题要求我们不能光记lcs是怎么打的,因为没这部分分,并且另外一个方程的转移要用 ...

随机推荐

  1. jQuery UI dialog

    初始化参数 对于 dialog 来说,首先需要进行初始化,在调用 dialog 函数的时候,如果没有传递参数,或者传递了一个对象,那么就表示在初始化一个对话框. 没有参数,表示按照默认的设置初始化对话 ...

  2. javascript继承(二)—创建对象的三种模式

    一.工厂模式 function createPerson(name,age){ var o = {}; o.name = name; o.age = age; o.sayHi = function() ...

  3. 我的第一个Node web程序

    NodeJS的流行也带来了开发由前端转到全栈,前端不再局限于页面如何展现,用户如何操作,也设计到整个应用的架构以及业务流程. 本篇来简单的通过实例,讲述node中web开发的模式. 参考来自<N ...

  4. 5.9-4用字符串生成器给字符串str追加1~10这10个数字

    package zfc; public class ZfcShcq { public static void main(String[] args) { // TODO Auto-generated ...

  5. 50行代码仿backbone_todos

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  6. 使用quartz 定时任务

    Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度. ...

  7. Lucene -- 实时索引

    lucene的实时搜索可以分成:实时和近实时的搜索. 实时只能依靠内存了. 近实时可以用lucene中提供org.apache.lucene.index.DirectoryReader.open(In ...

  8. python多态

    多态是面向对象语言的一个基本特性,多态意味着变量并不知道引用的对象是什么,根据引用对象的不同表现不同的行为方式.在处理多态对象时,只需要关注它的接口即可,python中并不需要显示的编写(像Java一 ...

  9. ssh整合常见的错误

    1.报错信息:java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refres ...

  10. jeecms内容显示条数

    1.按照1.2.3.4.5顺序显示 <div class="index-news"> [@cms_channel id='1'] <h2><span& ...