codevs 1862 最长公共子序列(求最长公共子序列长度并统计最长公共子序列的个数)
字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列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.
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里面的两段代码留存:
代码一:使用了滚动数组。
#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 最长公共子序列(求最长公共子序列长度并统计最长公共子序列的个数)的更多相关文章
- 最长公共子序列(LCS)问题 Longest Common Subsequence 与最长公告字串 longest common substr
问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk ...
- 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 ...
- Frogger POJ - 2253(求两个石头之间”所有通路中最长边中“的最小边)
题意 题目主要说的是,有两只青蛙,在两个石头上,他们之间也有一些石头,一只青蛙要想到达另一只青蛙所在地方,必须跳在石头上.题目中给出了两只青蛙的初始位置,以及剩余石头的位置,问一只青蛙到达另一只青 ...
- POJ-Common Substrings(后缀数组-长度不小于 k 的公共子串的个数)
题意: 长度不小于 k 的公共子串的个数 分析: 基本思路是计算 A 的所有后缀和 B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于 k 的部分全部加起来. 先将两个字符串连起来,中间 ...
- POJ 3415 Common Substrings(长度不小于K的公共子串的个数+后缀数组+height数组分组思想+单调栈)
http://poj.org/problem?id=3415 题意:求长度不小于K的公共子串的个数. 思路:好题!!!拉丁字母让我Wa了好久!!单调栈又让我理解了好久!!太弱啊!! 最简单的就是暴力枚 ...
- POJ 3415 Common Substrings 【长度不小于 K 的公共子串的个数】
传送门:http://poj.org/problem?id=3415 题意:给定两个串,求长度不小于 k 的公共子串的个数 解题思路: 常用技巧,通过在中间添加特殊标记符连接两个串,把两个串的问题转换 ...
- Common Substrings POJ - 3415(长度不小于k的公共子串的个数)
题意: 给定两个字符串A 和 B, 求长度不小于 k 的公共子串的个数(可以相同) 分两部分求和sa[i-1] > len1 sa[i] < len1 和 sa[i-1] < ...
- poj 3415 后缀数组 两个字符串中长度不小于 k 的公共子串的个数
Common Substrings Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 11469 Accepted: 379 ...
- 【POJ 3415】Common Substrings 长度不小于k的公共子串的个数
长度不小于k的公共子串的个数,论文里有题解,卡了一上午,因为sum没开long long!!! 没开long long毁一生again--- 以后应该早看POJ里的Discuss啊QAQ #inclu ...
随机推荐
- STM32学习笔记之EXTI(外部中断)
參考资料:STM32数据手冊.网络资料 =========================================切割线==================================== ...
- .Net-using-Class:String 类
ylbtech-.Net-using-Class:String类 1. 程序集 mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b ...
- C# xml 常规 保护 方法总结
一 使用xsd模式文件验证xml文件: xml文件: <?xml version="1.0" encoding="utf-8" ?> <Boo ...
- MongoDB 通过配置文件启动
mongod启动命令需指定一些参数启动服务,我们通过配置文件的方式配置这些参数加载配置. ./bin/mongod --config ./conf/mongodb.conf(或./bin/mongod ...
- bash shell seq的用法
seq 1 3 100 , 表示起始值为1, 间隔为3,终点值为100 #!/bin/bash aa=(1 2 3 17) #for i in 1 2 3 13 for i in ${aa[*]} d ...
- Flask刷新问题
修改页面中内容,特别是图片后,总是刷新不了.调试时,我常常通过修改端口来解决,从80-99不断改. 服务器部署,也遇到同样问题,重启web服务器,重启计算机都不行,网页已经改过来了,但是图片还是老图片 ...
- 程序员需要经纪人吗?10x 最好的程序员其生产力相当于同行的 10 倍~
原文地址 10x 起源于技术界一个流行的说法,即最好的程序员是超级明星,其生产力相当于同行的 10 倍: Google 园区以好玩的设施闻名:小憩舱.球坑.按摩.干洗.随便吃到饱的自助餐.(为了拍人才 ...
- C#.NET常见问题(FAQ)-如何修改Form不能修改窗体大小
把FormBorderSytle改一下就可以了,改成FixedSingle或者Fixed3D都可以 更多教学视频和资料下载,欢迎关注以下信息: 我的优酷空间: http://i.youku.com ...
- ZH奶酪:基于ionic.io平台的ionic消息推送功能实现
Hybrid App越来越火,Ionic的框架也逐渐被更多的人熟知. 在mobile app中,消息推送是很必要的一个功能. 国内很多ionic应用的推送都是用的极光推送,最近研究了一下Ionic自己 ...
- 一致性哈希算法——PHP实现代码
<?php /** * Flexihash - A simple consistent hashing implementation for PHP. * * The MIT License * ...