[ HAOI 2010 ] 最长公共子序列
\(\\\)
\(Description\)
求两个长度\(\le5000\)的大写字母串的\(LCS\)长度及个数,定义两\(LCS\)中某一字符在两序列出现位置有一处不同就视为不同。
\(\\\)
\(Solution\)
既然是基于下标不同的LCS那不就可以随便乱搞
求\(LCS\)的时候定义\(f[i][j]\)表示第一个序列处理到第\(i\)个位置,第二个序列处理到第\(j\)个位置时\(LCS\)的长度,类似的定义\(g[i][j]\)为该情况下\(LCS\)的个数。
大力\(DP\)就好,\(f[i][j]\)照常转移,\(g[i][j]\)需要根据转移的情况讨论:
首先若最后得到的答案转移自\(f[i-1][j]\)或\(f[i][j-1]\),那么要加上对应的方案数
若发现\(f[i-1][j-1]=f[i][j]\),证明新加的两个字符都没有用到,而累加了两次,所以要减掉
最后若转移还有\(s1[i]=s2[i]\)的情况,方案数也要对应加上\(f[i-1][j-1]\),注意到这一情况与上一情况必定是不同的,所以无需考虑冲突的部分。
直接开存不下,滚动数组。
\(\\\)
\(Code\)
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 5010
#define R register
#define gc getchar
#define mod 100000000
using namespace std;
char s1[N],s2[N];
int tot1,tot2,f[2][N],g[2][N];
int main(){
char c=gc();
while(!isupper(c)) c=gc();
s1[tot1=1]=c;
while(isupper(c=gc())) s1[++tot1]=c;
while(!isupper(c)) c=gc();
s2[tot2=1]=c;
while(isupper(c=gc())) s2[++tot2]=c;
g[1][0]=1;
for(R int i=0;i<=tot2;++i) g[0][i]=1;
for(R int i=1,now;i<=tot1;++i){
now=i&1;
for(R int j=1;j<=tot2;++j){
g[now][j]=0;
f[now][j]=max(f[now^1][j],f[now][j-1]);
if(s1[i]==s2[j]) f[now][j]=max(f[now][j],f[now^1][j-1]+1);
if(s1[i]==s2[j]) (g[now][j]+=g[now^1][j-1])%=mod;
if(f[now^1][j]==f[now][j]) (g[now][j]+=g[now^1][j])%=mod;
if(f[now][j-1]==f[now][j]) (g[now][j]+=g[now][j-1])%=mod;
if(f[now^1][j-1]==f[now][j]) (g[now][j]+=mod-g[now^1][j-1])%=mod;
}
}
printf("%d\n%d",f[tot1&1][tot2],g[tot1&1][tot2]);
return 0;
}
[ HAOI 2010 ] 最长公共子序列的更多相关文章
- 经典递归问题:0,1背包问题 kmp 用遗传算法来解背包问题,hash表,位图法搜索,最长公共子序列
0,1背包问题:我写笔记风格就是想到哪里写哪里,有很多是旧的也没删除,代码内部可能有很多重复的东西,但是保证能运行出最后效果 '''学点高大上的遗传算法''' '''首先是Np问题的定义: npc:多 ...
- DP_最长公共子序列/动规入门
学自:https://open.163.com/movie/2010/12/L/4/M6UTT5U0I_M6V2U1HL4.html 最长公共子序列:(本文先谈如何求出最长公共子序列的长度,求出最长公 ...
- 用python实现最长公共子序列算法(找到所有最长公共子串)
软件安全的一个小实验,正好复习一下LCS的写法. 实现LCS的算法和算法导论上的方式基本一致,都是先建好两个表,一个存储在(i,j)处当前最长公共子序列长度,另一个存储在(i,j)处的回溯方向. 相对 ...
- 动态规划之最长公共子序列(LCS)
转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...
- [Data Structure] LCSs——最长公共子序列和最长公共子串
1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...
- 动态规划求最长公共子序列(Longest Common Subsequence, LCS)
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- LintCode 77: 最长公共子序列
public class Solution { /** * @param A, B: Two string. * @return: the length of the longest common s ...
- 删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题
先要搞明白:最长公共子串和最长公共子序列的区别. 最长公共子串(Longest Common Substirng):连续 最长公共子序列(Longest Common Subsequence,L ...
- LCS(Longest Common Subsequence 最长公共子序列)
最长公共子序列 英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...
随机推荐
- gdb个人使用记录
参考博客:https://blog.csdn.net/zdy0_2004/article/details/80102076 安装gdb,查看版本确认成功: sudo apt install gdb g ...
- Linux下汇编语言学习笔记72 ---
这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...
- 递归算法(java)
最近在用EasyUI中的tree遍历节点的时候用到了递归算法,现总结如下: * 递归算法:在函数里调用自身,但必须确定递归出口,即结束条件,不然就是无限循环: * 递归一般解决的问题: ...
- 几道splay
hdu 1890 题意:每次将第i位到第i小数字所在的位置之间的位置翻转,每次输出第i小数字所在的位置 分析: 简单的splay处理区间翻转问题 有三点需要注意: 1.区间是1~n+2 2.此题里的查 ...
- Eclipse创建Maven多模块工程
一.创建父项目 [New]->[Maven Project] 在弹出界面中选择[Create a simple project...] 二.创建子项目 选中刚建的父项目,在弹出菜单中点击[New ...
- ZOJ 3868 GCD Expectation (容斥+莫比乌斯反演)
GCD Expectation Time Limit: 4 Seconds Memory Limit: 262144 KB Edward has a set of n integers {a1 ...
- QT如何修改字符编码格式
编辑-Select Encoding,然后在弹出窗口中修改字符编码.
- linux驱动之设备号与创建设备节点
设备号: 1.自己主动分配 major = register_chrdev(0,"first_drv",&first_sdv_fops);//注冊 注冊设备时给设备号写0, ...
- Linux ALSA声卡驱动之七:ASoC架构中的Codec
1. Codec简介(ad/da) 在移动设备中,Codec的作用可以归结为4种,分别是: 对PCM等信号进行D/A转换,把数字的音频信号转换为模拟信号 对Mic.Linein或者其他输入源的模拟信 ...
- 解决:sql2005 安装完后 没有服务的问题
去下面网站下载SQLEXPR_CHS.EXE然后安装就ok了.http://www.microsoft.com/downloadS/details.aspx?familyid=220549B5-0B0 ...