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;}    



原创粉丝点击