Description

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

Input

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

Output

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

Sample Input

ABCBDAB.
BACBBD.

Sample Output

4
7

HINT

首先,求最长子序列就是一个经典的dp了。f[i][j]表示s1到第i位,s2到第j位的最长子序列,f[i][j]=max(f[i-1][j-1]+(s1[i]==s2[j]),f[i-1][j],f[i][j-1])。

麻烦的就是方案的转移,我们另g[i][j]表示s1到第i位,s2到第j位的最长子序列的方案数。考虑以下的几种情况:

1.s1[i]==s2[j],f[i][j]=f[i-1][j-1]+1。g[i][j]=g[i-1][j-1]+(f[i-1][j]==f[i][j])*g[i-1][j]+(f[i][j-1]==f[i][j])*g[i][j-1],三种情况互不包含(g[i-1][j-1]指s1[i]与s2[j]配对;若f[i-1][j]==f[i][j]的话,一定有s1[i-1]与s2[j]配对(否则f不会相等),累加g[i-1][j];同理g[i][j-1]指的是s1[i]与s2[j-1]配对),直接加即可。

2.否则的话,f[i][j]=max(f[i-1][j],f[i][j-1]),若两者相等,则g[i][j]=g[i-1][j]+g[i][j-1]-g[i-1][j-1],因为中间部分两者都计算了一遍,否则就加上大者即可。

由于O(n^2)的空间肯定是开不下的,所以我们要利用滚动数组。

 1 #include<cstring>
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 using namespace std;
 6
 7 #define rhl (100000000)
 8 #define maxn 5010
 9 char s1[maxn],s2[maxn];
10 int f[2][maxn],g[2][maxn],n,m;
11
12 inline void dp()
13 {
14     n = strlen(s1+1),m = strlen(s2+1);
15     s1[n--] = s2[m--] = 0;
16     for (int i = 0;i <= m;++i) g[0][i] = 1;
17     for (int i = 1;i <= n;++i)
18     {
19         int p = i&1,q = p^1;
20         g[p][0] = 1;
21         for (int j = 1;j <= m;++j)
22         {
23             g[p][j] = 0;
24             if (s1[i] == s2[j])
25             {
26                 f[p][j] = f[q][j-1]+1;
27                 g[p][j] += g[q][j-1];
28                 if (f[q][j] == f[p][j]) g[p][j] += g[q][j];
29                 if (f[p][j-1] == f[p][j]) g[p][j] += g[p][j-1];
30             }
31             else
32             {
33                 f[p][j] = max(f[p][j-1],f[q][j]);
34                 if (f[p][j-1] > f[q][j]) g[p][j] = g[p][j-1];
35                 else if (f[q][j] > f[p][j-1]) g[p][j] = g[q][j];
36                 else
37                 {
38                     g[p][j] = g[q][j]+g[p][j-1];
39                     if (f[q][j-1] == f[p][j]) g[p][j] -= g[q][j-1];
40                 }
41             }
42             while (g[p][j] >= rhl) g[p][j] -= rhl;
43             while (g[p][j] < 0) g[p][j] += rhl;
44         }
45     }
46     printf("%d\n%d",f[n&1][m],g[n&1][m]);
47 }
48
49 int main()
50 {
51     freopen("2423.in","r",stdin);
52     freopen("2423.out","w",stdout);
53     scanf("%s%s",s1+1,s2+1);
54     dp();
55     fclose(stdin); fclose(stdout);
56     return 0;
57 }

View Code

转载于:https://www.cnblogs.com/mmlz/p/4281307.html

BZOJ 2423 最长公共子序列相关推荐

  1. BZOJ 2434 最长公共子序列

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2423 题意:求两个串的LCS以及LCS的个数. 思路: int f[2][N],g[2] ...

  2. BZOJ 2423: [HAOI2010]最长公共子序列

    2423: [HAOI2010]最长公共子序列 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1696  Solved: 674 [Submit][ ...

  3. bzoj 2423 [HAOI2010]最长公共子序列 动态规划

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

  4. BZOJ 3304: [Shoi2005]带限制的最长公共子序列( LCS )

    求个LCS, 只是有了限制, 多加一维表示匹配到z串的第几个, 然后用滚动数组 ------------------------------------------------------------ ...

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

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

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

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

  7. [DP] bzoj2423: [HAOI2010]最长公共子序列

    bzoj2423: [HAOI2010]最长公共子序列:https://www.lydsy.com/JudgeOnline/problem.php?id=2423 DP 神啊(DP都是神奇的东西) 第 ...

  8. LGOJ P2516 BZOJ2423 [HAOI2010]最长公共子序列 解题报告

    文章目录 题目链接 解题思路 对于第一问,这是LCS问题的经典模型 对于第二问,同样用DP来做 详细代码 题目链接 LGOJ BZOJ 解题思路 对于第一问,这是LCS问题的经典模型 我们设f[i][ ...

  9. 最长公共子序列(LCS)问题 Longest Common Subsequence 与最长公告字串 longest common substr...

    问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X="x0,x1,-,xm-1",序列Y=& ...

最新文章

  1. AI时代,如何缓解CMO的决策焦虑?
  2. 你想要的iOS 小技巧总结
  3. 使用network管理DD恢复全库操作步骤
  4. Scrapy框架----pipeline---------数据保存EXCEL
  5. Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果
  6. C++类构造析构调用顺序训练(复习专用)
  7. CodeForces 382B 数学推导
  8. Oracle中exp的使用2
  9. 那些你不知道的程序员的多重身份
  10. linux+arm+移除X11,关于ARM GTK/X11的问题,懂的指点一下
  11. 自动化Python+selenium 用这一篇学习就够了
  12. 常用网络通信协议结构图
  13. 基于javaweb+jsp的员工薪资工资管理系统(JavaWeb JSP MySQL Servlet SSM SpringBoot Layui Ajax)
  14. 51单片机 外部中断
  15. [爱分享]jeecms基础+导航条+例子分析
  16. Python入门(10)——宝可梦数据集探索
  17. 3J9D在contour-level之下
  18. 数据库:常用数据库的创建
  19. HTML+CSS制作知乎登录页面
  20. 基于vue技术栈制作自己的简历网站问题总结篇(入门vue基础项目)

热门文章

  1. 金蝶K3-WISE与管易云的集成方案
  2. CAD转PDF软件怎么选择
  3. 【天光学术】金融专业:互联网金融对保险合同制度适用的影响(节选)
  4. 办公室局域网主机为静态ip时配置路由器由器的方案
  5. JUC----ThreadLocal
  6. Redis常用命令|查询|删除|模糊操作
  7. 关于毕业设计汇报PPT
  8. 硬件设计——从零开始设计电路板
  9. shell脚本相关总结(1)
  10. Java工作一年半,第一次跳槽面试总结