[ 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 称为已 ...
随机推荐
- 树上启发式合并(DSU on tree)
//heavy-light decomposition style .//http://codeforces.com/blog/entry/44351 int cnt[maxn]; bool big[ ...
- noip模拟赛 街灯
分析:对于前30%的数据直接暴力模拟即可,对于另外30%的数据,因为每次的p是一样的,所以可以用莫队来维护,先离散化一下,再用一个桶统计次数. 100%的做法和之前做过的一道模拟赛题很像,当模数很小的 ...
- 170611 NOIP模拟赛
第一题没做出来不应该: 第二题不难想,就是写起来很麻烦: 第三题因为学了挺久的splay就直接写的splay,没太在意常数问题,一般情况下,第k值问题主席树是比splay稍快的: 盘子序列 [题目描述 ...
- multiple instance of mac app
一般情况下,mac系统上的应用程序只能启动一个实例,现在做项目,需要mac上同时启动多个实例,如何做呢,下面就说明完成这个功能的方法: 主要原理:利用 open -n Applications/XXX ...
- Ubuntu 16.04开机进入命令行(tty1)+分辨率调节+字体颜色设置+中文乱码解决(解决虚拟终端Ctrl+Alt+F1分辨率太大)
一.开机进入命令行模式(tty1) sudo vim /etc/default/grub 把GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash”改成GRUB_CMDLIN ...
- eclipse 安装egit插件
一.Eclipse上安装GIT插件EGit Eclipse的版本eclipse-java-helios-SR2-win32.zip(在Eclipse3.3版本找不到对应的 EGit插件,无法安装) E ...
- RoseLdz源代码下载地址
http://download.csdn.net/detail/u010296979/8152805
- 【JAVA】两点经纬度直线距离的计算
来自谷歌地图的计算公式: 通过JAVA的Math类各种方法调用.实现上述公式 private static double EARTH_RADIUS = 6378.137;// 单位千米 /** * 角 ...
- android实现跑马灯效果(能够实现两个以上跑马灯)
本文用了继承自TextView的MarqueeTextView来实现跑马灯效果.原因是,跑马灯效果是须要TextView拥有焦点才会跑动的.而有时候TextView获得焦点会有点耗时,造成要等待一段时 ...
- 我所不知的 javascript Object 的一些现象
1.我们都知道对象访问属性有两种方法,一种是使用 . 操作符,使用它添加的属性名必须满足标识符的命名规范:另一种是使用 [] 键访问的方法,可以接受任意UTF-8/Unicode字符串作为属性名,在E ...