牛客练习赛1 A - 矩阵

链接:https://www.nowcoder.com/acm/contest/2/A
来源:牛客网

题目描述

给出一个n * m的矩阵。让你从中发现一个最大的正方形。使得这样子的正方形在矩阵中出现了至少两次。输出最大正方形的边长。

输入描述:

第一行两个整数n, m代表矩阵的长和宽;
接下来n行,每行m个字符(小写字母),表示矩阵;

输出描述:

输出一个整数表示满足条件的最大正方形的边长。
示例1

输入

5 10
ljkfghdfas
isdfjksiye
pgljkijlgp
eyisdafdsi
lnpglkfkjl

输出

3

备注:

对于30%的数据,n,m≤100;
对于100%的数据,n,m≤500;

题解

二分,字符串$hash$。

可以二分答案,然后验证,验证的时候$O(n^2)$效率可以得到每一个正方形的$hash$值,判断一下即可,注意$hash$冲突,用了两次$hash$才过。

#include<bits/stdc++.h>
using namespace std;

long long base[2];
long long mod[2];
const int maxn = 500 + 10;
int n, m;
char s[maxn][maxn];
long long b[2][maxn * maxn];
long long sum[2][maxn][maxn];
long long h[2][maxn][maxn];
pair<long long, long long> pi[maxn * maxn];

void init() {
  base[0] = 131LL;
  base[1] = 313LL;
  mod[0] = 1e9 + 7;
  mod[1] = 1e9 + 7;
}

int check(int x) {
  for(int t = 0; t < 2; t ++) {
    for(int i = 0; i < n; i ++) {
      long long C = 0;
      for(int j = 0; j < x; j ++) {
        C = C * base[t] % mod[t];
        C = (C + s[i][j]) % mod[t];
      }
      sum[t][i][0] = C;
      for(int j = 1; j + x - 1 < m; j ++) {
        long long A = sum[t][i][j - 1];
        long long B = s[i][j - 1] * b[t][x - 1] % mod[t];
        A = (A - B + mod[t]) % mod[t];
        A = A * base[t] % mod[t];
        A = (A + s[i][j + x - 1]) % mod[t];
        sum[t][i][j] = A;
      }
    }
    for(int j = 0; j < m; j ++) {
      long long C = 0;
      for(int i = 0; i < x; i ++) {
        C = C * b[t][x] % mod[t];
        C = (C + sum[t][i][j]) % mod[t];
      }
      h[t][0][j] = C;
    }
    for(int i = 1; i + x - 1 < n; i ++) {
      for(int j = 0; j + x - 1 < m; j ++) {
        long long A = h[t][i - 1][j];
        long long B = sum[t][i - 1][j] * b[t][x * (x - 1)] % mod[t];
        A = (A - B + mod[t]) % mod[t];
        A = A * b[t][x] % mod[t];
        A = (A + sum[t][i + x - 1][j]) % mod[t];
        h[t][i][j] = A;
      }
    }
  }
  
  int sz = 0;
  for(int i = 0; i + x - 1 < n; i ++) {
    for(int j = 0; j + x - 1 < m; j ++) {
      pi[sz].first = h[0][i][j];
      pi[sz].second = h[1][i][j];
      sz ++;
    }
  }
  sort(pi, pi + sz);
  for(int i = 1; i < sz; i ++) {
    if(pi[i] == pi[i - 1]) return 1;
  }
  
  return 0;
}

int main() {
  init();
  b[0][0] = 1LL;
  b[1][0] = 1LL;
  for(int i = 1; i <= 250000; i ++) {
    b[0][i] = b[0][i - 1] * base[0] % mod[0];
    b[1][i] = b[1][i - 1] * base[1] % mod[1];
  }
  scanf("%d%d", &n, &m);
  for(int i = 0; i < n; i ++) {
    scanf("%s", s[i]);
  }
  int L = 1, R = min(n, m), 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;
}

/*
 
 5 10
 ljkfghdfas
 isdfjksiye
 pgljkijlgp
 eyisdafdsi
 lnpglkfkjl
 
 */

 

posted @ 2018-01-25 16:07  Fighting_Heart  阅读(579)  评论(0编辑  收藏  举报