51nod 1391 01串(hash+DP)
2015-08-14 22:30
357 查看
题目链接
题意:给定一个01串S,求出它的一个尽可能长的子串S[i..j],满足存在一个位置i<=x <=j, S[i..x]中0比1多,而S[x + 1..j]中1比0多。求满足条件的最长子串长度。
初步分析:假设子串S[i..j]是满足条件的一个最长子串,且i和j均不是边界(0<i && j<n-1),则S[i-1]一定是1,否则S[i-1, j]也满足条件且比S[i, j]长,矛盾。同理可推出S[j+1]是0。用类似的逻辑进一步可推出存在一个位置i<=x <=j, S[i..x]中0比1恰好多1个,而S[x + 1..j]中1比0恰好多1个。把原数组中所有的0用-1代替,子串01个数的比较就可以转换为子串和的正负。
思路:先处理i和j不是边界的情况,根据上面的初步分析,可以枚举x,然后分别考虑到x结尾的和为-1的最长子串的长度,以x+1开头的和为1的最长子串的长度。这两个子问题都可以通过hash来解决(类似于求最长01子串,使得0和1个数相等)。i,j是边界的情况特殊处理就好。
代码虽然写得挫,还是忍不住贴一个:
View Code
题意:给定一个01串S,求出它的一个尽可能长的子串S[i..j],满足存在一个位置i<=x <=j, S[i..x]中0比1多,而S[x + 1..j]中1比0多。求满足条件的最长子串长度。
初步分析:假设子串S[i..j]是满足条件的一个最长子串,且i和j均不是边界(0<i && j<n-1),则S[i-1]一定是1,否则S[i-1, j]也满足条件且比S[i, j]长,矛盾。同理可推出S[j+1]是0。用类似的逻辑进一步可推出存在一个位置i<=x <=j, S[i..x]中0比1恰好多1个,而S[x + 1..j]中1比0恰好多1个。把原数组中所有的0用-1代替,子串01个数的比较就可以转换为子串和的正负。
思路:先处理i和j不是边界的情况,根据上面的初步分析,可以枚举x,然后分别考虑到x结尾的和为-1的最长子串的长度,以x+1开头的和为1的最长子串的长度。这两个子问题都可以通过hash来解决(类似于求最长01子串,使得0和1个数相等)。i,j是边界的情况特殊处理就好。
代码虽然写得挫,还是忍不住贴一个:
#include <bits/stdc++.h> using namespace std; const int N = 1e6 + 11; char s ; int a ; int pre , suf ; int start , end ; int f[2*N]; int main() { freopen("in.txt", "r", stdin); while(1==scanf("%s", s+1)){ int n = strlen(s+1); for(int i=1; i<=n; i++){ a[i] = s[i]=='1' ? 1 : -1; } memset(f, 0x3f, sizeof(f)); memset(end, 0, sizeof(end)); pre[0] = 0; for(int i=1; i<=n; i++){ pre[i] = pre[i-1] + a[i]; int tmp = pre[i] + N; end[i] = max(0, i - f[tmp+1]); f[tmp] = min(f[tmp], i); } memset(f, 0, sizeof(f)); memset(start, 0, sizeof(start)); suf[n+1] = 0; for(int i=n; i>=1; i--){ suf[i] = suf[i+1] + a[i]; int tmp = suf[i] + N; start[i] = max(0, f[tmp-1] - i); f[tmp] = max(f[tmp], i); } int ans = 0; for(int i=1; i<=n; i++){ if(pre[i]<0 && suf[i+1]>0) ans = n; } for(int i=1; i<=n; i++){ if(pre[i]<0 && start[i+1]>0){ ans = max(ans, i+start[i+1]); } } for(int i=n; i>=1; i--){ if(suf[i]>0 && end[i-1]>0){ ans = max(ans, n+1-i + end[i-1]); } } for(int i=1; i<=n; i++){ if(end[i]>0 && start[i+1]>0){ ans = max(ans, end[i]+start[i+1]); } } printf("%d\n", ans); } return 0; }
View Code
相关文章推荐
- c++ primer plus 第七章-编程题7.13.5《求任意一个数的阶乘》
- 栈和堆的区别
- Android(java)学习笔记157:使用Dexdump等工具进行反编译
- 排序算法_C++(一)插入排序之直接插入排序
- HDU 4411 Arrest(费用流)
- 津津的储蓄计划
- hdu 5389 Zero Escape (dp)
- 浅析线程及同步
- 雷米 - 心理罪:城市之光(2015年8月11日)
- Java源文件编译出错:类文件包含错误的类 请删除该文件或确保文件位于正确的类路径子目录中
- epoll使用详解(精髓)
- 孪生素数
- 一次误用栈导致的错误。
- 雷米 - 心理罪:暗河(2015年8月9日)
- 无聊时候的思考
- 链表的普通应用
- wpf 生成自己格式的窗口并且按钮横向排序
- 状态压缩dp入门[HDU1074][HDU1065][POJ3254][POJ1185][HDU4359][POJ3311][POJ2411]
- 排列组合算法笔记
- IOS小技巧整理