题目描述 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 Description

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

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

输出描述 Output Description

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

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

样例输入 Sample Input

ABCBDAB.
BACBBD.

样例输出 Sample Output

4
7

 #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; #define maxn 5010
#define MOD 100000000
char A[maxn],B[maxn],cur;
int f[][maxn], g[][maxn]; int main()
{
scanf("%s%s", A + , B + );
int na = strlen(A + ), nb = strlen(B + );
A[na--] = '\0'; B[nb--] = '\0'; cur=;
for(int i = ; i <= nb; i++) g[][i] = ;
g[][] = g[][] = ; for(int i = ; i <= na; i++)
{
cur ^= ;
for(int j = ; j <= nb; j++)
{
if(A[i] == B[j]) f[cur][j] =f[cur^][j-] + ;
else f[cur][j] = max(f[cur^][j], f[cur][j-]); g[cur][j] = ;
if(f[cur][j] == f[cur^][j]) g[cur][j] += g[cur^][j];
if(f[cur][j] == f[cur][j-]) g[cur][j] += g[cur][j-];
if(f[cur][j] == f[cur^][j] && f[cur][j] == f[cur][j-] && f[cur^][j-] == f[cur][j])
g[cur][j] -= g[cur^][j-];
if(A[i] == B[j] && f[cur][j] == f[cur^][j-] + ) g[cur][j] += g[cur^][j-];
if(g[cur][j] > MOD) g[cur][j] %= MOD;
if(g[cur][j] < ) g[cur][j] = (g[cur][j] % MOD) + MOD;
}
}
printf("%d\n%d\n", f[cur][nb], g[cur][nb]);
return ;
}

参考1:http://blog.csdn.net/moep0/article/details/52760974

参考2:http://blog.csdn.net/litble/article/details/67640655

算法分析:

第一个问题可以参考最长公共子序列原题的题解。

第二个问题可以阅读参考1参考2的分析和代码自己理解。

这里摘抄参考1里面的两段代码留存:

代码一:使用了滚动数组。

 #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 = << ;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, , BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = , f = ; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -; c = Getchar(); }
while(isdigit(c)){ x = x * + c - ''; c = Getchar(); }
return x * f;
} #define maxn 5010
#define MOD 100000000
char A[maxn], B[maxn], cur;
int f[][maxn], g[][maxn]; int main() {
scanf("%s%s", A + , B + );
int na = strlen(A + ), nb = strlen(B + );
A[na--] = '\0'; B[nb--] = '\0'; for(int i = ; i <= nb; i++) g[][i] = ; g[][] = g[][] = ;
for(int i = ; i <= na; i++) {
cur ^= ;
for(int j = ; j <= nb; j++) {
f[cur][j] = max(f[cur^][j], f[cur][j-]);
if(A[i] == B[j]) f[cur][j] = max(f[cur][j], f[cur^][j-] + );
g[cur][j] = ;
if(f[cur][j] == f[cur^][j]) g[cur][j] += g[cur^][j];
if(f[cur][j] == f[cur][j-]) g[cur][j] += g[cur][j-];
if(f[cur][j] == f[cur^][j] && f[cur][j] == f[cur][j-] && f[cur^][j-] == f[cur][j]) g[cur][j] -= g[cur^][j-];
if(A[i] == B[j] && f[cur][j] == f[cur^][j-] + ) g[cur][j] += g[cur^][j-];
if(g[cur][j] > MOD) g[cur][j] %= MOD;
if(g[cur][j] < ) g[cur][j] = (g[cur][j] % MOD) + MOD;
}
} printf("%d\n%d\n", f[cur][nb], g[cur][nb]); return ;
}

代码二:不使用滚动数组,假如测试数据较小,可以AC。

 #include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#define mod 100000000
using namespace std;
string a,b;
int f[][],g[][];
int main(){
cin>>a>>b;
int l1=a.length()-,l2=b.length()-;
a=' '+a,b=' '+b;
for(int i=;i<=l1;i++)g[i][]=;
for(int i=;i<=l2;i++)g[][i]=;
for(int i=;i<=l1;i++)
for(int j=;j<=l2;j++)
{
if(a[i]==b[j])
{
f[i][j]=f[i-][j-]+;
g[i][j]=g[i-][j-];
if(f[i][j]==f[i][j-])g[i][j]=(g[i][j]+g[i][j-])%mod;
if(f[i][j]==f[i-][j])g[i][j]=(g[i][j]+g[i-][j])%mod;
}
else
{
f[i][j]=max(f[i-][j],f[i][j-]);
if(f[i][j]==f[i-][j])g[i][j]=(g[i][j]+g[i-][j])%mod;
if(f[i][j]==f[i][j-])g[i][j]=(g[i][j]+g[i][j-])%mod;
if(f[i][j]==f[i-][j-])g[i][j]-=g[i-][j-],g[i][j]=(g[i][j]+mod)%mod;
}
}
cout<<f[l1][l2]<<endl<<g[l1][l2]%mod;
return ;
}

codevs 1862 最长公共子序列(求最长公共子序列长度并统计最长公共子序列的个数)的更多相关文章

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

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

  2. POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)

    Description A substring of a string T is defined as: T( i, k)= TiTi+1... Ti+k-1, 1≤ i≤ i+k-1≤| T|. G ...

  3. Frogger POJ - 2253(求两个石头之间”所有通路中最长边中“的最小边)

    题意 ​ 题目主要说的是,有两只青蛙,在两个石头上,他们之间也有一些石头,一只青蛙要想到达另一只青蛙所在地方,必须跳在石头上.题目中给出了两只青蛙的初始位置,以及剩余石头的位置,问一只青蛙到达另一只青 ...

  4. POJ-Common Substrings(后缀数组-长度不小于 k 的公共子串的个数)

    题意: 长度不小于 k 的公共子串的个数 分析: 基本思路是计算 A 的所有后缀和 B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于 k 的部分全部加起来. 先将两个字符串连起来,中间 ...

  5. POJ 3415 Common Substrings(长度不小于K的公共子串的个数+后缀数组+height数组分组思想+单调栈)

    http://poj.org/problem?id=3415 题意:求长度不小于K的公共子串的个数. 思路:好题!!!拉丁字母让我Wa了好久!!单调栈又让我理解了好久!!太弱啊!! 最简单的就是暴力枚 ...

  6. POJ 3415 Common Substrings 【长度不小于 K 的公共子串的个数】

    传送门:http://poj.org/problem?id=3415 题意:给定两个串,求长度不小于 k 的公共子串的个数 解题思路: 常用技巧,通过在中间添加特殊标记符连接两个串,把两个串的问题转换 ...

  7. Common Substrings POJ - 3415(长度不小于k的公共子串的个数)

    题意: 给定两个字符串A 和 B, 求长度不小于 k 的公共子串的个数(可以相同) 分两部分求和sa[i-1] > len1  sa[i] < len1  和  sa[i-1] < ...

  8. poj 3415 后缀数组 两个字符串中长度不小于 k 的公共子串的个数

    Common Substrings Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 11469   Accepted: 379 ...

  9. 【POJ 3415】Common Substrings 长度不小于k的公共子串的个数

    长度不小于k的公共子串的个数,论文里有题解,卡了一上午,因为sum没开long long!!! 没开long long毁一生again--- 以后应该早看POJ里的Discuss啊QAQ #inclu ...

随机推荐

  1. mac下的docker的Docker.raw占用空间很大?

    如图所示,60G,我的天呢? 其实这个只是系统分配给docker的逻辑硬盘大小,应该是指docker最大可用的硬盘空间,实际占用没有这么大 实际占用大小: 另外: 参考:https://github. ...

  2. 使用Idea创建多Module工程

    1. 点击 New -- Project 2. 设置工程父Pom, 如下 <?xml version="1.0" encoding="UTF-8"?> ...

  3. C++二维数组 取地址 复制给 二维指针

    本来应该是个简单的问题,但是我就不明白了,为什么会段错误了... #include<stdio.h> #define UINT32 unsigned int UINT32 NType1_X ...

  4. 多线程学习-ListenableFuture使用介绍以及示例

    Guava为Java并行编程Future提供了很多有用扩展,其主要接口为ListenableFuture,并借助于Futures静态扩展.ListenableFuture顾名思义就是可以监听的Futu ...

  5. freemarker怎么把数据显示到页面中?

    第一步  创建一个User.java文件 来两个变量       public class User {       private String userName;         private ...

  6. asp.net单元测试及查看代码覆盖率详细示例

    在vs2008中创建单元测试 一,打开vs2008,创建一个类库VSTSDemo.因为我在学习的时候用的就是vs2008,其它版本的vs,方法应该差不多,大家自己研究吧 :) 删除掉默认生成的类,然后 ...

  7. iOS开发-UIScrollView图片无限循环

    关于UIScrollView图片浏览的例子有很多,之前也写过类似方面的文章,关于UIScrollView的图片循环在新闻类的App基本上是比较常见的一种情况就是图片浏览,然后根据不同的图片显示不同的内 ...

  8. JQuery-Dialog(弹出窗口,遮蔽窗口)

    在Ajax中经常用到的弹出窗口和遮蔽窗口.自己写肯定是一个最佳方案,但时间和成本上,还是决定了寻找现成的吧.大概罗列一下.需要我满足我几个条件 一定要简洁方便 拥有遮蔽功能,Model Dialog ...

  9. CSS3动画的回调处理

    我们在做js动画的时候,很多时候都需要做回调处理,如在一个动画完成后触发一个事件.一个动画完成后执行另外一个动画等等,但在使用CSS3动画时能不能捕获到运动的状态做回调处理呢? CSS3动画也是可以做 ...

  10. 转:利用Eclipse CDT 阅读C/C++代码

    转自: https://www.oschina.net/question/234345_41419 排版与说明都很不错,推荐一看.