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优化的更多相关文章

  1. HDU 5745 La Vie en rose (DP||模拟) 2016杭电多校联合第二场

    题目:传送门. 这是一道阅读理解题,正解是DP,实际上模拟就能做.pij+1 指的是 (pij)+1不是 pi(j+1),判断能否交换输出即可. #include <iostream> # ...

  2. HDU 5745 La Vie en rose 暴力

    La Vie en rose 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5745 Description Professor Zhang woul ...

  3. 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 ...

  4. 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 ...

  5. hdu5745--La Vie en rose (DP+bitset)

    好题,学到新姿势! 题意:给两个字符串 a 和 b ,b可以进行变换,规则是可以任意交换相邻两个字符的位置,但是不可以有交叉(例如3和4交换,5和6交换 互不影响,但是2和3,3和4就不可以).求a中 ...

  6. hdu5745 La Vie en rose 巧妙地dp+bitset优化+滚动数组减少内存

    /** 题目:hdu5745 La Vie en rose 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5745 题意:题目给出的变换规则其实就是交换相邻 ...

  7. La Vie en rose (模拟)

    #include<bits/stdc++.h> using namespace std; ; ; int T, n, m; char str1[maxm], str2[maxn]; int ...

  8. HDU 5313——Bipartite Graph——————【二分图+dp+bitset优化】

    Bipartite Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  9. HDU5745-La Vie en rose-字符串dp+bitset优化

    这题现场的数据出水了,暴力就能搞过. 标解是拿bitset做,转移的时候用bitset优化过的操作(与或非移位)来搞,复杂度O(N*M/w) w是字长 第一份标程的思路很清晰,然而后来会T. /*-- ...

随机推荐

  1. HDU 1695 (莫比乌斯反演) GCD

    题意: 从区间[1, b]和[1, d]中分别选一个x, y,使得gcd(x, y) = k, 求满足条件的xy的对数(不区分xy的顺序) 分析: 虽然之前写过一个莫比乌斯反演的总结,可遇到这道题还是 ...

  2. jrtplib跨网络通讯NAT穿透问题解决方法

    前几篇文章讲了使用jrtplib在Android和pc端进行通讯的方法 在实际项目中,手机端和pc端一般不会在同一个子网内,两者之间联络可能要走路由器之类的NAT(网络地址转换 Network Add ...

  3. hdu 5407 CRB and Candies(组合数+最小公倍数+素数表+逆元)2015 Multi-University Training Contest 10

    题意: 输入n,求c(n,0)到c(n,n)的所有组合数的最小公倍数. 输入: 首行输入整数t,表示共有t组测试样例. 每组测试样例包含一个正整数n(1<=n<=1e6). 输出: 输出结 ...

  4. C#发送Email邮件(实例:QQ邮箱和Gmail邮箱)

    下面用到的邮件账号和密码都不是真实的,需要测试就换成自己的邮件账号. 需要引用: using System.Net.Mail; using System.Text; using System.Net; ...

  5. uC/OS - III 移植 IAR平台

    关于移植uC/OS-III 网上已经有很多教程了此处只是做个记录 首先下载源码然后解压得到下面的文件: 然后在模版工程里新建各种文件夹: 最后全部都添加进工程: OK了,编译一下,惊呆了,竟然 0错误 ...

  6. PowerDesigner Vs Enterprise Architect

    注: 以下文中PD表示PowerDesigner,EA表示Enterprise Architect 最近一直在做设计方面的事情,之前一直在用PD.有个阿里过来的同事说阿里都是用EA,我就抽空小研究了一 ...

  7. 提取数字、英文、中文、过滤重复字符等SQL函数(含判断字段是否有中文)

    --SQL 判断字段值是否有中文 create  function  fun_getCN(@str  nvarchar(4000))    returns  nvarchar(4000)      a ...

  8. Android-day02_广播

    1.什么是广播 貌似一个人大声喊一句话,别人听到了这就是广播 2.在android中广播有标准广播和有序广播 标准广播也就是发送一个广播,所有人都能同一时间接收到 有序广播则是有顺序的广播,发送的时候 ...

  9. maven学习系列教程,第一课(web项目的搭建)

    1.现在一般eclipse都已经装好了maven板块,无需自行下载安装,所以我们的第一步就是新建一个maven project 2地址使用默认的就行 3这边筛选一下,选择webapp 4. 5.建好后 ...

  10. 【原】Storm序列化

    5. Storm高级篇 序列化 Dynamic typing Custom serialization Java serialization Component-specific serializat ...