清北学堂模拟赛d5t5 exLCS
分析:比较巧妙的一道题.经典的LCS算法复杂度是O(nm)的,理论上没有比这个复杂度更低的算法,除非题目有一些限制.这道题中两个字符串的长度不一样,f[i][j]如果表示第一个串前i个,第二个串前j个的最长公共子序列的话,复杂度会爆.但是LCS的长度很小,能不能换一种状态的表示方法呢?
回想0/1背包问题的变形,如果体积特别大,价值特别小,我们可以把价值定义在状态里面,设f[i][j]表示前i个物品中价值为j的最小体积,最后扫一遍j看看符不符合条件就可以了,对于这道题我们可以也可以沿用这样的思路,把LCS的长度放到状态里面,设f[i][j]表示str1的前i个,LCS的长度为j的已经匹配到的str2的最左下标,先预处理一下当前位置的字母的下一次出现的位置,然后就可以递推了.
当dp题中状态很大,答案很小的时候可以把答案定义到状态中,最后扫一下看看是否满足要求就可以了.这种方法有点像二分一样:我知道了答案,检验答案是否可行.
代码中求nextt数组的做法值得学习!
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int maxn = , inf = 0x7ffffff;
int f[maxn][maxn], nextt[][], n, m, ans;
char a[], b[]; int main()
{
scanf("%s%s", a, b);
n = strlen(a);
m = strlen(b);
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
f[i][j] = inf;
for (int i = ; i < ; i++)
nextt[m][i] = inf;
for (int i = m - ; i >= ; i--)
{
memcpy(nextt[i], nextt[i + ], sizeof(nextt[i]));
nextt[i][b[i] - 'a'] = i;
}
f[][] = nextt[][a[] - 'a'];
for (int i = ; i <= n; i++)
f[i][] = -;
for (int i = ; i < n - ; i++)
for (int j = ; j <= n && f[i][j] < inf; j++)
{
f[i + ][j] = min(f[i + ][j], f[i][j]);
if (j < n)
f[i + ][j + ] = min(f[i + ][j + ], nextt[f[i][j] + ][a[i + ] - 'a']);
}
for (int i = n; i >= ; i--)
if (f[n - ][i] != inf)
{
ans = i;
break;
}
printf("%d\n", ans); return ;
}
清北学堂模拟赛d5t5 exLCS的更多相关文章
- 清北学堂模拟赛day7 数字碰撞
/* clj:水题别人都满分你不是你就完了,所以说水题一定要细心一点,有这么几个细节:①前导零的处理,全是零的时候要特判②换行要注意,不要多大一行,剩下就是水水的模拟了 */ #include< ...
- 清北学堂模拟赛d4t1 a
分析:大模拟,没什么好说的.我在考场上犯了一个超级低级的错误:while (scanf("%s",s + 1)),导致了死循环,血的教训啊,以后要记住了. /* 1.没有发生改变, ...
- 清北学堂模拟赛day7 错排问题
/* 考虑一下已经放回m本书的情况,已经有书的格子不要管他,考虑没有书的格子,不考虑错排有(n-m)!种,在逐步考虑有放回原来位置的情况,已经放出去和已经被占好的格子,不用考虑,剩下全都考虑,设t=x ...
- 清北学堂模拟赛day7 石子合并加强版
/* 注意到合并三堆需要枚举两个端点,其实可以开一个数组记录合并两堆的结果,标程好像用了一个神奇的优化 */ #include<iostream> #include<cstdio&g ...
- 清北学堂模拟赛d6t6 棋盘迷宫
3.棋盘迷宫(boardgame.pas/c/cpp)(boardgame.in/out)时间限制:5s/空间限制:256M[题目描述]小 A 和小 Z 是非常要好的朋友, 而且他们都对迷宫游戏非常有 ...
- 清北学堂模拟赛d1t2 火柴棒 (stick)
题目描述众所周知的是,火柴棒可以拼成各种各样的数字.具体可以看下图: 通过2根火柴棒可以拼出数字“1”,通过5根火柴棒可以拼出数字“2”,以此类推. 现在LYK拥有k根火柴棒,它想将这k根火柴棒恰好用 ...
- 清北学堂模拟赛d1t1 位运算1(bit)
题目描述LYK拥有一个十进制的数N.它赋予了N一个新的意义:将N每一位都拆开来后再加起来就是N所拥有的价值.例如数字123拥有6的价值,数字999拥有27的价值.假设数字N的价值是K,LYK想找到一个 ...
- 清北学堂模拟赛d2t6 分糖果(candy)
题目描述总共有n颗糖果,有3个小朋友分别叫做L,Y,K.每个小朋友想拿到至少k颗糖果,但这三个小朋友有一个共同的特点:对3反感.也就是说,如果某个小朋友拿到3颗,13颗,31颗,333颗这样数量的糖果 ...
- 清北学堂模拟赛d2t5 吃东西(eat)
题目描述一个神秘的村庄里有4家美食店.这四家店分别有A,B,C,D种不同的美食.LYK想在每一家店都吃其中一种美食.每种美食需要吃的时间可能是不一样的.现在给定第1家店A种不同的美食所需要吃的时间a1 ...
随机推荐
- openStack logo
- Coursera Algorithms week4 基础标签表 练习测验:Java autoboxing and equals
1. Java autoboxing and equals(). Consider two double values a and b and their corresponding Double v ...
- java普通代码块、静态代码块、默认构造方法的执行顺序
package test; class Parent{ { System.out.println("父类普通代码块"); } static{ System.out.println( ...
- jqxtree异步加载部门树
整体思路 A.要想实现异步加载第一次加载的是一级部门 B.加载一级部门,如果有子部门,部门前面带+号,没有子部门,部门前面没有+号(+号也就是点击可以展开) C.在sql中实现如果有子部门默认都加载一 ...
- activiti安装-------安装插件
对上面的放大
- 推荐给Web前端开发人员的一些书籍(从基础到架构阶段)
有很多人问我说作为一个前端开发人员都需要看一些什么书籍,尤其是刚入门的新手,今天我整理了一下推荐给大家,大佬绕过. HTML+CSS+JavaScript 网页设计 从入门到精通 作为一个前端新手,强 ...
- datatable 的使用方法
遍历datatable的方法 +方法一:DataTable dt = dataSet.Tables[0];for(int i = 0 ; i < dt.Rows.Count ; i++){str ...
- JVM面试总结
1. Java虚拟机的内存布局(运行时数据区) 参考:https://www.cnblogs.com/lostyears/articles/8984171.html 2. GC算法及几种垃圾收集器 ...
- 参加2016华为codecraft编程精英挑战赛后感
2016年4月参加了华为的软件比赛. 关于比赛:给了一道图论的np-hard问题.刚开始完全不知道怎么入手,请教过师兄,自己也琢磨过,没有什么万全的解决方法.注意,这里说的是万全的办法.本科搞算法时候 ...
- Ubuntu 系统的常用快捷键
Ubuntu操作基本快捷键 ibus-setup :设置系统输入法 scp filename username@serverIp:/home/xxx/xxx/filename 回车输入该usern ...