牛客練習賽 A-矩陣(二維矩陣雜湊+二分)
阿新 • • 發佈:2018-12-14
題目描述
給出一個n * m的矩陣。讓你從中發現一個最大的正方形。使得這樣子的正方形在矩陣中出現了至少兩次。輸出最大正方形的邊長。
輸入描述:
第一行兩個整數n, m代表矩陣的長和寬; 接下來n行,每行m個字元(小寫字母),表示矩陣;
輸出描述:
輸出一個整數表示滿足條件的最大正方形的邊長。
示例1
輸入
5 10 ljkfghdfas isdfjksiye pgljkijlgp eyisdafdsi lnpglkfkjl
輸出
3
備註:
對於30%的資料,n,m≤100; 對於100%的資料,n,m≤500;
解題思路:首先想到的二分正方形長度,然後我們對矩陣進行二維雜湊一下,這樣對於每個子矩陣我們都有對應的一個雜湊值,這樣我們二分的條件就找該雜湊值有沒有出現兩次即可,出現的次數我們用map來記錄一下。
不會雜湊的戳這裡:雜湊演算法詳解
AC程式碼:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<string> #include<math.h> #include<cstdlib> #include<stdlib.h> #include<queue> #include<map> #include<set> #include<stack> #define bug printf("*********\n"); #define mem0(a) memset(a, 0, sizeof(a)); #define mem1(a) memset(a, -1, sizeof(a)); #define finf(a, n) fill(a, a+n, INF); #define in1(a) scanf("%d" ,&a); #define in2(a, b) scanf("%d%d", &a, &b); #define in3(a, b, c) scanf("%d%d%d", &a, &b, &c); #define out1(a) printf("%d\n", a); #define out2(a, b) printf("%d %d\n", a, b); #define pb(G, b) G.push_back(b); #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; typedef long long LL; typedef unsigned long long uLL; typedef pair<LL, pair<int, LL> > LLppar; typedef pair<int, int> par; typedef pair<LL, int> LLpar; const LL mod = 2147493647; const LL INF = 1e9+7; const uLL base1 = 131; const uLL base2 = 233; const int MAXN = 300010; const int MAXM = 300010; const double pi = acos(-1); int n, m; char mp[510][510]; uLL has[510][510]; uLL p1[510], p2[510]; map<uLL, int> mmp; void init() { p1[0] = p2[0] = 1; for(int i = 1; i <= 505; i ++) { p1[i] = p1[i-1]*base1; p2[i] = p2[i-1]*base2; } } void Hash() { has[0][0] = 0; has[0][1] = 0; has[1][0] = 0; for(int i = 1; i <= n; i ++) { for(int j = 1; j <= m; j ++) { has[i][j] = has[i][j-1]*base1 + mp[i][j] - 'a'; } } for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j ++) { has[i][j] = has[i-1][j]*base2 + has[i][j]; } } } bool check(int x) { mmp.clear(); for(int i = x; i <= n; i ++) { for(int j = x; j <= m; j ++) { uLL k = has[i][j] - has[i-x][j]*p2[x] - has[i][j-x]*p1[x] + has[i-x][j-x]*p1[x]*p2[x]; mmp[k] ++; if(mmp[k] >= 2) return true; } } return false; } int main() { init(); while(~scanf("%d%d", &n, &m)) { for(int i = 1; i <= n; i ++) { scanf("%s", mp[i]+1); } Hash(); int l = 0, r = 600, ans = 0; while(l <= r) { int mid = (l+r)/2; if(check(mid)) { l = mid+1; ans = mid; }else { r = mid-1; } } printf("%d\n", ans); } return 0; }