题意:求一个矩阵的最大回文子矩阵。
分奇偶,二分长度,hash判回文。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef unsigned long long lng;
const int maxn = 500;
const int x = 100000007;
int num[maxn][maxn];
lng hash[4][maxn][maxn], xp[maxn];
int n, m;
void prework()
{
memset(hash, 0, sizeof(hash));
scanf("%d %d", &n, &m);
for(int i = 0; i < n; ++i)
for(int j = 0; j < m; ++j)
scanf("%d", &num[i][j]);
for(int i = 0; i < n; ++i)
{
hash[0][i][0] = num[i][0];
for(int j = 1; j < m; ++j)
hash[0][i][j] = hash[0][i][j - 1] * x + num[i][j];
hash[1][i][m - 1] = num[i][m - 1];
for(int j = m - 2; j >= 0; --j)
hash[1][i][j] = hash[1][i][j + 1] * x + num[i][j];
}
for(int i = 0; i < m; ++i)
{
hash[2][i][0] = num[0][i];
for(int j = 1; j < n; ++j)
hash[2][i][j] = hash[2][i][j - 1] * x + num[j][i];
hash[3][i][n - 1] = num[n - 1][i];
for(int j = n - 2; j >= 0; --j)
hash[3][i][j] = hash[3][i][j + 1] * x + num[j][i];
}
}
lng gethash(int num, int r, int a, int b)
{
if(num == 0 || num == 2)
{
lng ans = hash[num][r][b];
if(a > 0) ans -= xp[b - a + 1] * hash[num][r][a - 1];
return ans;
}
else
return hash[num][r][a] - xp[b - a + 1] * hash[num][r][b + 1];
}
bool check(int len)
{
bool sign = true;
for(int i = 0; i + len <= n; ++i)
{
for(int j = 0; j + len <= m; ++j)
{
for(int k = i; k < i + len; ++k)
{
lng h1 = gethash(0, k, j, j + len / 2 - 1);
lng h2 = gethash(1, k, j + len / 2 + (len % 2), j + len - 1);
if(h1 != h2) {
sign = false;
break;
}
}
for(int k = j; k < j + len && sign; ++k)
{
lng h1 = gethash(2, k, i, i + len / 2 - 1);
lng h2 = gethash(3, k, i + len / 2 + (len % 2), i + len - 1);
if(h1 != h2) {
sign = false;
break;
}
}
if(sign) return true;
else sign = true;
}
}
return false;
}
void solve()
{
int ans = 1;
if(check(2))
{
int l = 1, r = min(n, m);
if(r % 2) r--;
r /= 2;
while(l < r)
{
int mid = (l + r) / 2 + 1;
if(check(2 * mid)) l = mid;
else r = mid - 1;
}
ans = max(2 * l, ans);
}
int l = 0, r = min(n, m);
if(r % 2 == 0) r--;
r /= 2;
while(l < r)
{
int mid = (l + r) / 2 + 1;
if(check(2 * mid + 1)) l = mid;
else r = mid - 1;
}
ans = max(ans, 2 * l + 1);
printf("%d\n", ans);
}
int main()
{
freopen("in.txt", "r", stdin);
xp[0] = 1;
for(int i = 1; i <= 300; ++i) xp[i] = xp[i - 1] * (lng)x;
int t; cin >> t;
while(t--)
{
prework();
solve();
}
return 0;
}