hdu 5745 La Vie en rose DP + bitset优化
http://acm.hdu.edu.cn/showproblem.php?pid=5745
这题好劲爆啊。dp容易想,但是要bitset优化,就想不到了。
先放一个tle的dp。复杂度O(n * m)的
第一个串,记作str[],第二个记作sub[]
思路就是,设dp[i][j][k]表示,匹配了sub的前i个,以str的第j个结尾,然后sub[i]有三种状态,0表示不变化,1表示和前一个,2表示和后一个。
那么以求dp[i][j][0]为列
因为需要的是判断str的第j个结尾是否和sub的前i个完全匹配。
那么,要使得dp[i][j][0]为true,必然需要前i - 1个和j - 1个匹配成功。就是要递推过来。
那么dp[i][j][0] = (dp[i - 1][j - 1][0] || dp[i - 1][j - 1][1]) && (str[j] == sub[i])
其他的类似啦。
可以滚动下数组。
不清0的话,直接用DFN代替即可。这样的复杂度就是O(n * m),没有常数。但是还是TLE.
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 1e5 + ;
char str[maxn], sub[maxn];
int dp[][maxn][];
int DFN;
char ans[maxn];
void work() {
DFN++;
int lenstr, lensub;
scanf("%d%d", &lenstr, &lensub);
scanf("%s", str + );
scanf("%s", sub + );
// dp[0][0][0] = DFN;
for (int i = ; i <= lenstr; ++i) dp[][i][] = DFN;
int now = ;
for (int i = ; i <= lensub; ++i) {
now = !now;
for (int j = ; j <= lenstr; ++j) {
// if ((dp[i - 1][j - 1][0] || dp[i - 1][j - 1][1]) && str[j] == sub[i]) {
// dp[i][j][0] = true;
// }
// if (dp[i - 1][j - 1][2] && str[j] == sub[i - 1]) {
// dp[i][j][1] = true;
// }
// if ((dp[i - 1][j - 1][0] || dp[i - 1][j - 1][1]) && sub[i + 1] == str[j]) {
// dp[i][j][2] = true;
// }
if ((dp[!now][j - ][] == DFN || dp[!now][j - ][] == DFN) && str[j] == sub[i]) {
dp[now][j][] = DFN + ;
}
if (dp[!now][j - ][] == DFN && str[j] == sub[i - ]) {
dp[now][j][] = DFN + ;
}
if ((dp[!now][j - ][] == DFN || dp[!now][j - ][] == DFN) && str[j] == sub[i + ]) {
dp[now][j][] = DFN + ;
}
}
DFN++;
}
for (int i = ; i <= lenstr; ++i) {
ans[i] = '';
if (dp[now][i][] == DFN || dp[now][i][] == DFN || dp[now][i][] == DFN) {
// printf("1");
ans[i - lensub + ] = '';
}
}
ans[lenstr + ] = '\0';
printf("%s\n", ans + );
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
int t;
scanf("%d", &t);
while (t--) work();
return ;
}
然后百度了一个bitset的优化。
考虑用bitset<1e5> dp[5000][k]
dp[i][k]
表示,处理了sub的前i个,当前sub的状态是k,然后匹配整个str串的结果就是dp[i][k],因为dp[i][k]是一个长度为1e5的01串嘛。也就是dp[i][k]就是匹配好的结果了。
那么,要快速计算dp[i][0],只需要(dp[i - 1][0] | dp[i - 1][1]) << 1
比如前2个匹配好的结果是"10"和"11"然后匹配成的第三位,就是"011",关键看看第三位,是1,也就是上面的dp[i - 1][j - 1][k] = true的意思。就是前面的匹配好了,但是还要看看str[j]和sub[i]的相等情况。
要想这一位是true,必然要这一位和sub对应相等。但是我们一次要算出整一个结果,而不是一个一个地算,那么,预处理个pos[26]的bitset就可以,&一下,就是要对应位置是1的,才是true。
3478ms,我是卡过去的

后来一直TLE
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset> const int maxn = 1e5 + ;
bitset<maxn> dp[][];
char str[maxn], sub[maxn];
bitset<maxn>pos[]; void init() {
for (int i = ; i <= ; ++i) {
for (int j = ; j <= ; ++j) {
dp[i][j].reset();
}
}
for (int i = ; i < ; ++i) pos[i].reset();
}
char ans[maxn];
void work() {
init();
int lenstr, lensub;
scanf("%d%d", &lenstr, &lensub);
scanf("%s%s", str + , sub + );
for (int i = ; i <= lenstr; ++i) {
pos[str[i] - 'a'][i] = ;
}
dp[][] = pos[sub[] - 'a'];
if (lensub >= ) dp[][] = pos[sub[] - 'a'];
int now = ;
for (int i = ; i <= lensub; ++i) {
now = !now;
dp[now][] = ((dp[!now][] | dp[!now][]) << ) & pos[sub[i] - 'a'];
dp[now][] = (dp[!now][] << ) & pos[sub[i - ] - 'a'];
if (i < lensub) {
dp[now][] = ((dp[!now][] | dp[!now][]) << ) & pos[sub[i + ] - 'a'];
}
}
for (int i = ; i <= lenstr; ++i) {
if (i + lensub - > lenstr) {
ans[i] = '';
} else {
if (dp[now][][i + lensub - ] || dp[now][][i + lensub - ]) {
ans[i] = '';
} else ans[i] = '';
}
}
ans[lenstr + ] = '\0';
printf("%s\n", ans + );
// printf("\n");
}
int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
int t;
scanf("%d", &t);
while (t--) work();
return ;
}
hdu 5745 La Vie en rose DP + bitset优化的更多相关文章
- HDU 5745 La Vie en rose (DP||模拟) 2016杭电多校联合第二场
题目:传送门. 这是一道阅读理解题,正解是DP,实际上模拟就能做.pij+1 指的是 (pij)+1不是 pi(j+1),判断能否交换输出即可. #include <iostream> # ...
- HDU 5745 La Vie en rose 暴力
La Vie en rose 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5745 Description Professor Zhang woul ...
- HDU 5745 La Vie en rose
La Vie en rose Time Limit: 14000/7000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- hdu 5745 La Vie en rose(2016多校第二场)
La Vie en rose Time Limit: 14000/7000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- hdu5745--La Vie en rose (DP+bitset)
好题,学到新姿势! 题意:给两个字符串 a 和 b ,b可以进行变换,规则是可以任意交换相邻两个字符的位置,但是不可以有交叉(例如3和4交换,5和6交换 互不影响,但是2和3,3和4就不可以).求a中 ...
- hdu5745 La Vie en rose 巧妙地dp+bitset优化+滚动数组减少内存
/** 题目:hdu5745 La Vie en rose 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5745 题意:题目给出的变换规则其实就是交换相邻 ...
- La Vie en rose (模拟)
#include<bits/stdc++.h> using namespace std; ; ; int T, n, m; char str1[maxm], str2[maxn]; int ...
- HDU 5313——Bipartite Graph——————【二分图+dp+bitset优化】
Bipartite Graph Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- HDU5745-La Vie en rose-字符串dp+bitset优化
这题现场的数据出水了,暴力就能搞过. 标解是拿bitset做,转移的时候用bitset优化过的操作(与或非移位)来搞,复杂度O(N*M/w) w是字长 第一份标程的思路很清晰,然而后来会T. /*-- ...
随机推荐
- HDU 1672 Cuckoo Hashing
Cuckoo Hashing Description One of the most fundamental data structure problems is the dictionary pro ...
- UVa 10892 (GCD) LCM Cardinality
我一直相信这道题有十分巧妙的解法的,去搜了好多题解发现有的太过玄妙不能领会. 最简单的就是枚举n的所有约数,然后二重循环找lcm(a, b) = n的个数 #include <cstdio> ...
- BZOJ3105: [cqoi2013]新Nim游戏
题解: 线性基?类似于向量上的基底. 此题题解戳这里:http://blog.csdn.net/wyfcyx_forever/article/details/39477673 代码: #include ...
- SelectSingleNode和SelectNodes区别
SelectSingleNode:选择匹配 XPath 表达式的第一个 XmlNodeSelectNodes:选择匹配 XPath 表达式的结点集合 XmlNodeList
- Fatal NI connect error 12170
Fatal NI connect error 12170 转载:http://www.xifenfei.com/1812.html 今天在一台服务器的日志文件中,发现如下信息: Fatal NI co ...
- NSIS 2.0界面快速入门
NSIS 2.0 版本支持定制的用户界面.所谓的 Modern UI(下称 MUI) 就是一种模仿最新的 Windows 界面风格的界面系统.MUI 改变了 NSIS 脚本的编写习惯,它使用 NSIS ...
- [反汇编练习] 160个CrackMe之011
[反汇编练习] 160个CrackMe之011. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- 【C#学习笔记】检测进程是否存在并关闭
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- 【C#学习笔记】读SQL Server2008
using System; using System.Data.SqlClient; namespace ConsoleApplication { class Program { static voi ...
- FTP文件上传与下载
实现FTP文件上传与下载可以通过以下两种种方式实现(不知道还有没有其他方式),分别为:1.通过JDK自带的API实现:2.通过Apache提供的API是实现. 第一种方式:使用jdk中的ftpClie ...