牛客网 Wannafly模拟赛 矩阵 二分+hash矩阵
来源:互联网 发布:大数据接入dpi 编辑:程序博客网 时间:2024/06/07 08:13
题目链接
题意:
给出一个n * m的矩阵。让你从中发现一个最大的正方形。使得这样子的正方形在矩阵中出现了至少两次。输出最大正方形的边长。
思路:
一开始没想明白二分, 首先判断具有单调性,长度为3的正方形存在,长度为2的也一定存在...如果最大长度为6的存在,而长度为7的一定不存在.
然后就是想怎么去快速判断两个矩阵是否相等啊,肯定是hash了.于是hash我算错了复杂度,其实线性就可以hash矩阵了,我算成n3.还是姿势太少。
这里我对每一个位置的字母的贡献都按照 第w个位置(一行一行的 ,从1....n*m最多500*500).base^w来计算.先维护一个二维前缀和(利用容斥原理维护二维前缀和的复杂度是n2,查询任意一个一直长度矩阵的和复杂度也是n2,都利用容斥原理)
然后二分答案,去check. check的时候发现这样hash的话每个正方形内部从1....s个位置 前一个位置比后一个多乘一个base,但是任意两个矩阵之间是差很多的,这里我们让两个矩阵对应的位置次数对齐即可.
用了map,hash值不合适被卡常数了,复杂度 n*mlog^2 。把hash值改小才过,
700ms+
#include<bits/stdc++.h>using namespace std;const int maxn = 500+10; typedef unsigned long long ll; char s[maxn][maxn];int n,m; ll x[maxn*maxn],h[maxn*maxn];ll f[maxn][maxn]; void Hash(){ memset(f,0,sizeof(f)); h[0]=0;x[0]=1; int k = 0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ ++k; x[k]=x[k-1]*19; f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+x[k]*(s[i][j]-'a'); }}map<ll,int>mp;ll tmp ;bool check(int ans){ mp.clear(); for(int i=ans;i<=n;i++){ for(int j=ans;j<=m;j++){ tmp = f[i][j]-f[i-ans][j]-f[i][j-ans]+f[i-ans][j-ans]; tmp = tmp*x[(n-i)*m+m-j]; if(mp.count(tmp)) return true; mp[tmp]=1; } } return false;}int main(){ while(~scanf("%d%d",&n,&m)){ for(int i=1;i<=n;i++) scanf("%s",s[i]+1); Hash(); int l=1,r=min(n,m),ans=0,mid; while(l<=r){ mid = r+l >> 1; if(check(mid)) ans = mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); } return 0;}
于是手写一个
70ms+
#include<bits/stdc++.h>using namespace std;typedef unsigned long long ull;const ull base=123;const int maxn=4e5+10;const int hashh= 1e6+10;char s[511][511];ull num[511*511],f[511][511];int n,m; struct hashmap{ull a[maxn];int head[hashh];int nxt[maxn];int siz;void init(){memset(head,-1,sizeof head);siz = 0;}bool find(ull val){int tmp = (val % hashh + hashh) % hashh;for(int i = head[tmp];i!=-1;i = nxt[i]){if(val == a[i]) return true;}return false;}void add(ull val){int tmp = (val % hashh + hashh) % hashh;if(find(val)) return ;a[siz] = val;nxt[siz] = head[tmp];//令next指向-1;head[tmp] = siz++; }}Hash;void init(){memset(f,0,sizeof f);num[0]=1;int cnt = 0;for(int i = 1; i <= n;i++) for(int j = 1;j <= m;j++) { cnt++; num[cnt] = num[cnt-1]*base; f[i][j] = f[i-1][j] + f[i][j-1] -f[i-1][j-1] + (s[i][j]-'0')*num[cnt]; } return ;}bool check(int x){Hash.init();for(int i = x;i <= n;i++) for(int j = x;j <= m;j++) { ull tmp = f[i][j] - f[i][j - x] - f[i - x][j] + f[i - x][j - x]; tmp = tmp * num[(n - i) * m + m - j]; if(Hash.find(tmp) == true) return true; Hash.add(tmp); } return false;}int main(){while(~scanf("%d %d",&n,&m)){for(int i = 1;i <= n;i++) scanf("%s",s[i]+1);init();int l = 1,r=min(n,m),mid,ans = -1;while(l<=r){mid = (l + r) >> 1;if(check(mid))l = mid + 1,ans = mid;elser = mid - 1;}printf("%d\n",ans);}return 0;}
阅读全文
0 0
- Wannafly模拟赛 矩阵 [矩阵hash+二分]
- 牛客网 Wannafly模拟赛 矩阵 二分+hash矩阵
- 牛客网 Wannafly模拟赛 矩阵 二分+hash矩阵
- Wannafly模拟赛 矩阵 二维矩阵hash
- 【大二最后一题】Wannafly模拟赛 矩阵【二分+二维字符串Hash】
- Wannafly模拟赛5 A split 二分
- 矩阵hash+二分(慎用map)
- Wannafly模拟赛3 贝伦卡斯泰露 【折半搜索+hash,状压dp】
- 二分矩阵
- 10.9wannafly模拟赛
- Wannafly模拟赛4
- Wannafly模拟赛3
- bzoj1567[JSOI2008]Blue Mary的战役地图 二分+矩阵hash
- bzoj1141(矩阵hash)
- 矩阵hash + KMP
- 数字矩阵和模拟矩阵
- Wannafly模拟赛3 题解
- Wannafly模拟赛3 题解
- mac下安装和使用brew
- hdu1150—Machine Schedule(最小点覆盖)
- Spring的配置及引用
- fprintf函数
- UNIX环境高级编程习题——第八章
- 牛客网 Wannafly模拟赛 矩阵 二分+hash矩阵
- UIView
- leetcode 235. Lowest Common Ancestor of a Binary Search Tree
- java 中的大数据类型(BigInteger和BigDecimal)
- Linux上安装wildfly-10.1.0.Final并部署iServer9D war包
- Spring Boot 学习——Controller的使用
- 《鸟哥的Linux私房菜 基础学习篇(第三版)》习题与解析(四)
- HDU ACM2014
- JsTree树不出来 报Uncaught TypeError: Cannot read property 'children' of undefined