题目描述 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. GDSL 1.7 发布,C语言通用数据结构库

    GDSL 1.7 修复了 interval-heap 模块的一个小 bug. GDSL (通用数据结构库) 包含一组程序用于操作各种数据结构.这是一个可移植的库,完全由 ANSI C 编写.为 C 开 ...

  2. Spring(AbstractRoutingDataSource)实现动态数据源切换

    转自: http://blog.51cto.com/linhongyu/1615895 一.前言 近期一项目A需实现数据同步到另一项目B数据库中,在不改变B项目的情况下,只好选择项目A中切换数据源,直 ...

  3. 第一章 第一个dubbo项目

    为了安全:服务启动的ip全部使用10.10.10.10 版本: dubbo:2.5.5 重要的网址: dubbo的github:https://github.com/alibaba/dubbo dub ...

  4. C++/Php/Python 语言执行shell命令

    编程中经常需要在程序中使用shell命令来简化程序,这里记录一下. 1. C++ 执行shell命令 #include <iostream> #include <string> ...

  5. scikit-learn——快速入门 - daniel-D(转)

    ML sklearn快速入门 申明:该系列博客是学习 sklearn 的笔记,内容将涵盖大部分机器学习的方法.本人微博@迅猛龙Daniel,能力有限,存在任何问题,希望共同交流.该博客采用马克飞象专业 ...

  6. postgres配置只能让某一个ip的主机登陆

    https://stackoverflow.com/questions/11753296/configure-postgresql-to-work-for-only-localhost-or-spec ...

  7. java实现文件的断点续传的下载

    java的断点续传是基于之前java文件下载基础上的功能拓展 首先设置一个以线程ID为名的下载进度文件, 每一次下载的进度会保存在这个文件中,下一次下载的时候,会根据进度文件里面的内容来判断下载的进度 ...

  8. 抽屉柜式MCC柜中PROFIBUS设备推荐波特率及相应传输距离

    抽屉柜式MCC柜中PROFIBUS设备推荐波特率及相应传输距离.例如以下图所看到的: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L ...

  9. 解决jetty runner锁定js

    在web.xml中添加 <servlet> <!-- Override init parameter to avoid nasty --> <!-- file locki ...

  10. 通读Cheerio文档

    前言 cheerio是一款非常实用的nodejs第三方包,适用于服务端(nodejs端)处理html.它有着与jquery及其相似(几乎是一致)的api,速度飞快,使用灵活,而且不仅能够处理html, ...