[HAOI2010][DP]最长公共子序列
来源:互联网 发布:58网络经纪人 编辑:程序博客网 时间:2024/06/05 19:23
[Problem 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的一个子序列。
对给定的两个字符序列,求出他们最长的公共子序列长度,以及最长公共子序列个数。
[Algorithm]
DP 容斥
[Analysis]
最长公共子序列是一个经典的dp模型。但是加上统计个数就比较麻烦。我们可以很容易的想到这样的递推式
when s[i] == s[j]
f[i][j] = f[i - 1][j - 1] + 1
way[i][j] = way[i - 1][j - 1]
way[i][j] += way[i][j - 1] (f[i][j] == f[i][j - 1)
way[i][j] += way[i - 1][j] (f[i][j] == f[i - 1][j])
when s[i] != s[j]
f[i][j] = max(f[i - 1][j], f[i][j - 1])
way[i][j] = 0;
way[i][j] += way[i][j - 1](f[i][j] == f[i][j - 1])
way[i][j] += way[i - 1][j](f[i][j] == f[i - 1][j])
第一种情况是没有问题的,但第二种情况有问题。如果f[i][j - 1]和f[i - 1][j]都是由f[i - 1][j - 1]推出来的,那么way[i][j]里面相当于加了两遍的way[i - 1][j - 1],在这种情况下要加上way[i - 1][j - 1],这样就没有问题了。
[Pay Attention]
想了半天没有想到会有重复的情况,还是看了别人的题解才知道的……所以对于这种拿不准的转移要多想想,实在不行多出几组数据或者写个暴力对拍……还有一个蛋疼的地方,题目要求mod的数是1e8,我看成了1e9……要小心
[Code]
/************************************************************** Problem: 2423 User: gaotianyu1350 Language: C++ Result: Accepted Time:1668 ms Memory:1352 kb****************************************************************/ #include <cstdio>#include <cmath>#include <cstring>#include <cstdlib>#include <iostream>using namespace std; const int MOD = (int)1e8;const int MAXN = 5010; int f[2][MAXN] = {{0}}, way[2][MAXN] = {{0}};string s1, s2; inline void update(int &maxLen, int &maxWay, int len, int way){ if (len > maxLen) { maxLen = len; maxWay = way; } else if (len == maxLen) maxWay = (maxWay + way) % MOD;} int main(){ //freopen("input.txt", "r", stdin); int pre = 0, now = 1; getline(cin, s1, '.'); getchar(); getline(cin, s2, '.'); int len1 = s1.length(), len2 = s2.length(); for (int i = 0; i <= len2; i++) way[pre][i] = 1; way[now][0] = 1; for (int i = 1; i <= len1; i++) { for (int j = 1; j <= len2; j++) { f[now][j] = f[now][j - 1]; way[now][j] = way[now][j - 1]; update(f[now][j], way[now][j], f[pre][j], way[pre][j]); if (s1[i - 1] == s2[j - 1]) update(f[now][j], way[now][j], f[pre][j - 1] + 1, way[pre][j - 1]); if (s1[i - 1] != s2[j - 1] && f[now][j - 1] == f[pre][j] && f[pre][j - 1] == f[now][j]) way[now][j] = (way[now][j] + MOD - way[pre][j - 1]) % MOD; } pre ^= 1; now ^= 1; } printf("%d\n%d\n", f[pre][len2], way[pre][len2]);}
0 0
- [HAOI2010][DP]最长公共子序列
- [HAOI2010]最长公共子序列
- bzoj 2423: [HAOI2010]最长公共子序列 (DP)
- [BZOJ2423][HAOI2010]最长公共子序列(DP)
- BZOJ2423/HAOI2010 最长公共子序列
- BZOJ2423 [HAOI2010]最长公共子序列
- BZOJ 2423: [HAOI2010]最长公共子序列
- BZOJ2423 [HAOI2010]最长公共子序列 (LCS)
- 洛谷P2516 [HAOI2010]最长公共子序列
- 2423: [HAOI2010]最长公共子序列
- 【bzoj2423】【HAOI2010】最长公共子序列
- bzoj2423 [HAOI2010]最长公共子序列
- 洛谷 P2516 [HAOI2010]最长公共子序列
- BZOJ 2423: [HAOI2010]最长公共子序列|动态规划
- 【HAOI2010】BZOJ2423 BSOJ2775 CODEVS1862 洛谷P2516 最长公共子序列
- 【动态规划】BZOJ2423: [HAOI2010]最长公共子序列
- bzoj 2423 [HAOI2010]最长公共子序列 动态规划
- 最长公共子序列--DP
- C#与Windows API对应数据类型
- UML九种图 之 顺序图和协作图
- shape文件用法一:在Android中,用XML文件来设置颜色的渐变
- 用V4L2接口读取UVC camera的数据以及V4L2驱动测试程序
- iOS 获取全局唯一标示符
- [HAOI2010][DP]最长公共子序列
- DOM解析xml和插入创建
- Android 4.2 输入流程分析
- 图片处理之图片缩略图
- Leetcode: Sum Root to Leaf Numbers 理解分析
- 下面就是开始自己制作第一个模块
- 去除List中重复元素
- ACM-二分搜索之Can you solve this equation?——hdu2199
- cgi配合boa使用web服务器