URAL - 1486 二维字符串HASH
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1486
题意:给定一个n*m的字符矩阵,问你是否存在两个不重合(可以有交集)的正方形矩阵完全一致, 存在输出正方形的最大边长和两个正方形的左上角坐标,不存在则输出0
思路:二维字符串Hash,二分正方形的长度,然后Hash判断即可。
#define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<map> #include<vector> #include<time.h> #include<stack> #include<cmath> using namespace std; typedef long long int LL; typedef unsigned long long int ULL; const int MAXN = 500 + 24; const ULL pr = 9973; const ULL pc = 100000007; char str[MAXN][MAXN]; pair<int, int>ans1, ans2; map<ULL, pair<int, int>>mp; ULL Hash[MAXN][MAXN]; bool check(int n,int m,int x){ mp.clear(); ULL t1 = 1; for (int i = 0; i < x; i++){ t1 *= pr; } for (int i = 0; i < n; i++){ ULL e = 0; for (int j = 0; j < x; j++){ e = e*pr + (str[i][j] - 'a'); } for (int j = 0; j + x <= m; j++){ Hash[i][j] = e; if (j + x < m){ e = e*pr - t1*(str[i][j] - 'a') + (str[i][j + x] - 'a'); } } } ULL t2 = 1; for (int i = 0; i < x; i++){ t2 *= pc; } for (int j = 0; j+x <= m; j++){ ULL e = 0; for (int i = 0; i < x; i++){ e = e*pc + Hash[i][j]; } for (int i = 0; i + x <= n; i++){ if (mp.find(e) != mp.end()){ ans1 = mp[e]; ans2.first = i, ans2.second = j; return true; } mp.insert(make_pair(e, make_pair(i, j))); if (i + x < n){ e = e*pc - t2*Hash[i][j] + Hash[i + x][j]; } } } return false; } int main(){ //#ifdef kirito // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); //#endif // int start = clock(); int n, m; while (~scanf("%d%d", &n,&m)){ for (int i = 0; i < n; i++){ scanf("%s", str[i]); } int l = 1, r = min(n, m), mid; while (r >= l){ mid = (r + l) >> 1; if (check(n,m,mid)){ l = mid + 1; } else{ r = mid - 1; } } if (r&&check(n,m,r)){ printf("%d\n", r); printf("%d %d\n", ans1.first + 1, ans1.second + 1); printf("%d %d\n", ans2.first + 1, ans2.second + 1); } else{ printf("0\n"); } } //#ifdef LOCAL_TIME // cout << "[Finished in " << clock() - start << " ms]" << endl; //#endif return 0; }