【URAL 1486】Equal Squares

题意:求给定字符矩阵中相同正方形矩阵的最大边长和这两个相同正方形的位置

第一次写字符串哈希,选两个不同的模数进行二维字符串哈希。

本来应该取模判断相等后再暴力扫矩阵来判断,但是我看到《Hash在信息学竞赛中的一类应用》中这么写道:

于是我还会再次判重吗?肯定不会!!!

于是这样写完后就调啊调,调出几个像没用unsigned long long这样的脑残错误后交上去就A了233

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef unsigned long long ll;
const int N = 503;
const ll p = 100007;
const int p1 = 1007;
const int p2 = 10007;

struct node {
	ll to; int nxt, x, y;
	node (ll _to = 0, int _nxt = 0, int _x = 0, int _y = 0) : to(_to), nxt(_nxt), x(_x), y(_y) {}
} E[N * N];

char s[N][N];
int point[p + 3], cnt, n, m;
ll hash1[N][N], hash[N][N], pow1[N], pow2[N];


void ins(ll from, ll to, int x, int y) {E[++cnt] = node(to, point[from], x, y); point[from] = cnt;}
int __(ll t) {
	ll f = t % p;
	for(int i = point[f]; i; i = E[i].nxt)
		if (E[i].to == t) return i;
	return 0;
}
bool _(int t) {
	memset(point, 0, sizeof(point)); cnt = 0;
	ll num;
	for(int i = 1; i <= n - t + 1; ++i)
		for(int j = 1; j <= m - t + 1; ++j) {
			num = hash[i + t - 1][j + t - 1] - hash[i + t - 1][j - 1] * pow1[t] - hash[i - 1][j + t - 1] * pow2[t] + hash[i - 1][j - 1] * pow1[t] * pow2[t];
			if (__(num)) return 1;
			ins(num % p, num, i, j);
		}
	return 0;
}

int main() {
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; ++i) scanf("%s", s[i] + 1);
	pow1[0] = 1; pow2[0] = 1;
	for(int i = 1; i < N; ++i) pow1[i] = pow1[i - 1] * p1, pow2[i] = pow2[i - 1] * p2;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j) {
			hash1[i][j] = hash1[i][j - 1] * p1 + (int) s[i][j];
			hash[i][j] = hash[i - 1][j] * p2 + hash1[i][j];
		}
	int left = 0, right = n == m ? n - 1 : min(n, m), mid;
	while (left < right) {
		mid = (left + right + 1) >> 1;
		if (_(mid)) left = mid;
		else right = mid - 1;
	}
	if (left == 0) puts("0");
	else {
		printf("%d\n", left);
		memset(point, 0, sizeof(point)); cnt = 0;
		for(int i = 1; i <= n - left + 1; ++i)
			for(int j = 1; j <= m - left + 1; ++j) {
			ll num = hash[i + left - 1][j + left - 1] - hash[i + left - 1][j - 1] * pow1[left] - hash[i - 1][j + left - 1] * pow2[left] + hash[i - 1][j - 1] * pow1[left] * pow2[left];
			if (right = __(num)) {
				printf("%d %d\n%d %d\n", E[right].x, E[right].y, i, j);
				return 0;
			}
			ins(num % p, num, i, j);
		}
	}
	
	return 0;
}

神奇的哈希啊,我到现在都对你的时间复杂度感到迷茫~

posted @ 2016-05-21 16:29  abclzr  阅读(276)  评论(0编辑  收藏  举报