HDU 4618 Palindrome Sub-Array (HASH + 枚举)
来源:互联网 发布:磁力链接搜索引擎源码 编辑:程序博客网 时间:2024/05/16 12:04
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题目:给出一个矩阵,选出一个子方阵,使得每一行每一列都是一个回文串
http://acm.hdu.edu.cn/showproblem.php?pid=4618
做法:预处理之后,O(n ^ 3)枚举,然后 O(1)判断选中的矩形是否是回文矩阵。
然后 考虑怎么预处理,首先从左往右,从右往左,从上往下,从下往下进行hash之后,这样就能O(1)判断任意一个一维区间是否为回文串。
看似还需要O(n)的枚举行和列。
再做一步处理,up[i][j][k]表示对于每i行的[j , k]这个区间,往上匹配,连续的[j , k]区间都是回文串的有几个。
那么对于枚举的连长为l 的方阵来说,便是判断 up[i][j][k] >= l 。i表示方阵底部的行号,[j , k]是列区间。
同理列也是同样 的处理,那么这样的预处理是O(n ^ 3),总体复杂度是O(n ^ 3)。
但是竟然卡了内存,只能将其优化 。
我们枚举底部的行,那么对于 up[][][]数组便可以进行滚动,然后 是left[][][],每次枚举底部的和,那么就算是已经固定了一维,那么down[i][j] 表示,对于当前枚举的是行为j的话,那么表示第i列的区间[j , k]。
貌似还不如别人 很暴力的方法快= =
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <string>using namespace std;typedef unsigned int ull;const int N = 302;const ull HASH = 1000000007;ull fac[N] = {1};ull l[N][N] , r[N][N] , u[N][N] , d[N][N];int up[2][N][N] , lef[N][N];int n , m , a[N][N];int main () { #ifndef ONLINE_JUDGE freopen("input.txt","r",stdin); #endif int t ; scanf ("%d" , &t); for (int i = 1 ; i < N ; i ++) { fac[i] = fac[i - 1] * HASH; } while (t --) { scanf ("%d %d" , &n , &m); for (int i = 1 ; i <= n ; i ++) { for (int j = 1 ; j <= m ; j ++) { scanf ("%d", &a[i][j]); } } for (int i = 1 ; i <= n ; i ++) { l[i][0] = 0; r[i][m + 1] = 0; for (int j = 1 ; j <= m ; j ++) { l[i][j] = l[i][j - 1] * HASH + a[i][j]; } for (int j = m ; j >= 1 ; j --) { r[i][j] = r[i][j + 1] * HASH + a[i][j]; } } for (int j = 1 ; j <= m ; j ++) { d[0][j] = 0 ; u[n + 1][j] = 0; for (int i = 1 ; i <= n ; i ++) { d[i][j] = d[i - 1][j] * HASH + a[i][j]; } for (int i = n ; i >= 1 ; i --) { u[i][j] = u[i + 1][j] * HASH + a[i][j]; } } memset (up , 0 , sizeof(up)); int ans = 1; for (int i = 1 ; i <= n ; i ++) { memset (lef, 0 , sizeof(lef)); for (int j = 1 ; j <= m ; j ++) { for (int k = j ; k <= m ; k ++) { ull l_r = l[i][k] - l[i][j - 1] * fac[k - j + 1]; ull r_l = r[i][j] - r[i][k + 1] * fac[k - j + 1]; if (l_r == r_l) { up[i & 1][j][k] = up[(i + 1) & 1][j][k] + 1; } else up[i & 1][j][k] = 0; } } for (int j = 1 ; j <= m ; j ++) { for (int k = 1 ; k <= i ; k ++) { ull u_d = d[i][j] - d[k - 1][j] * fac[i - k + 1]; ull d_u = u[k][j] - u[i + 1][j] * fac[i - k + 1]; if (u_d == d_u) { lef[j][k] = lef[j - 1][k] + 1; } else lef[j][k] = 0; } } for (int k = 1 ; k < i ; k ++) { int l = i - k + 1; for (int j = 1 ; j + l - 1 <= m ; j ++) { if (up[i & 1][j][j + l - 1] >= l) { if (lef[j + l - 1][k] >= l) ans = max (ans , l); } } } } printf ("%d\n" , ans); } return 0;}
- HDU 4618 Palindrome Sub-Array (HASH + 枚举)
- HDU 4618Palindrome Sub-Array(暴力枚举每一个正方形)
- Hdu 4618 Palindrome Sub-Array
- hdu 4618 Palindrome Sub-Array
- HDU 4618 Palindrome Sub-Array
- Hdu 4618 Palindrome Sub-Array
- HDU-4618-Palindrome Sub-Array
- hdu 4618 Palindrome Sub-Array
- HDU 4618 Palindrome Sub-Array
- HDU 4618 Palindrome Sub-Array 解题报告
- hdu 4618——Palindrome Sub-Array
- hdu 4618 Palindrome Sub-Array(dp)
- HDU 4618 Palindrome Sub-Array 二分(奇偶)+hash判断是否对称
- 2013 多校第二场 hdu 4618 Palindrome Sub-Array
- hdu 4618 Palindrome Sub-Array 多校第二场
- HDU 4618 Palindrome Sub-Array(最大回文子矩阵)
- HDU 4618 Palindrome Sub-Array(Manacher、二分)
- hdu4618 Palindrome Sub-Array
- J2SE 必知必会(七)
- 08-一个IP绑定多个域名(根据ServerName)
- windows下LIB和DLL的区别与使用
- Stones(hdu1896)优先队列
- 存储入门框架
- HDU 4618 Palindrome Sub-Array (HASH + 枚举)
- json转换数据时候,报there is a cycle in the hierarchy!
- N的N次方
- CSDN暑假学习记事
- SecureCRT向Linux系统传送和接收文件
- mscs下oracle数据库安装
- QT插件学习
- 【专题】图的连通性问题
- HDU 4601 Letter Tree