题目描述 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. RSA加密解密及RSA签名和验证及证书

    RSA加密解密及RSA签名和验证及证书 公钥是给别人的 发送密文使用公钥加密 验证签名使用公钥验证 私钥是自己保留的 接受密文使用私钥解密 发送签名使用私钥签名 上述过程逆转是不行的,比如使用私钥加密 ...

  2. Binary Tree ZigZag Level Order Traversal leetcode java

    题目: Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from lef ...

  3. layer.msg();怎么关闭

    var index = layer.msg(); $.ajax("","",function(){ layer.close(index) })

  4. 八一八android开发规范(一种建议)

    开发规范重不重要了,不言而喻.这里就给大家说一故事把——据<圣经·旧约·创世记>第11章记载,是当时人类联合起来兴建,希望能通往天堂的高塔.为了阻止人类的计划,上帝让人类说不同的语言,使人 ...

  5. 大数据开发实战:Hive优化实战3-大表join大表优化

    5.大表join大表优化 如果Hive优化实战2中mapjoin中小表dim_seller很大呢?比如超过了1GB大小?这种就是大表join大表的问题.首先引入一个具体的问题场景,然后基于此介绍各自优 ...

  6. laravel5.5 dingo/api+jwt-auth

    因为laravel5.5 具有发现包功能,只要包做了兼容laravel5.5就可以不用在config/app.php添加额外代码了. 集成dingo/api github:https://github ...

  7. MAC高效软件必备-落雨

    更新时间:2017年09月19日23:45:29 使用MAC有一年多,最想说的莫过于如何打造一个高效的使用Mac的体验. 1. MAC任务栏管理,窗口切换 1. Mac任务栏管理(类似于Windows ...

  8. Dubbo-Fail to decode request due to: RpcInvocation

    使用Dubbo进行服务化,遇到如下错误: Caused by: com.alibaba.dubbo.remoting.RemotingException: Fail to decode request ...

  9. 海马模拟器连不上ADB的解决方法

    http://yunpan.cn/c3xMeYhvVsEIq  访问密码 fa8d先暂时用这个工具吧,官方提供的,不过目前不是最终版,后面会加入到模拟器中 adb connect 127.0.0.1: ...

  10. OpenStack云计算之路-Mitaka 版本

    1.1 云计算简介 云计算(英语:cloud computing ),是一种基于互联网的计算方式,通过这种方式,共享的软硬件资源和信息可以按需求提供给计算机各种终端和其他设备. 云计算是继1980年代 ...