• 二维hash


    题目描述

    给出一个n * m的矩阵。让你从中发现一个最大的正方形。使得这样子的正方形在矩阵中出现了至少两次。输出最大正方形的边长。

    输入描述:

    第一行两个整数n, m代表矩阵的长和宽;
    接下来n行,每行m个字符(小写字母),表示矩阵;

    输出描述:

    输出一个整数表示满足条件的最大正方形的边长。




    https://www.nowcoder.com/acm/contest/submit/f8363c912a4c48a28b80f47e7102b6b8?ACMContestId=2&tagId=4


    做了一题二维hash的题。
    我的这个方法应该不是正宗的二维hash。
    我的做法是,先对每一行进行一维hash
    然后对于每一个正方形,就有k(正方形边长)个hash值,然后再对这个值hash
    然后要手写一个类似map的东西,不然超时。
    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef unsigned long long int LL;
    int n, m;
    const int maxn = 1e3 + 20, seed = 131;
    char str[maxn][maxn];
    LL po[maxn], str_hash[maxn][maxn];
    int ask(int row, int be, int len) {
        return str_hash[row][be + len - 1] - po[len] * str_hash[row][be - 1];
    }
    LL thash[maxn];
    const int MOD = 10007;
    struct StringHash {
        int first[MOD + 2], num;
        LL EdgeNum[1000000 + 2];
        int tonext[1000000 + 2];
        void init() {
            num = 0;
            memset(first, -1, sizeof first);
        }
        void toinsert(LL val) {
            EdgeNum[num] = val;
            int u = val % MOD;
            tonext[num] = first[u];
            first[u] = num++;
        }
        bool has(LL val) {
            int u = val % MOD;
            for (int i = first[u]; ~i; i = tonext[i]) {
                if (EdgeNum[i] == val) return true;
            }
            return false;
        }
    } my;
    bool check(int val) {
        my.init();
        for (int i = 1; i + val - 1 <= m; ++i) {
            for (int j = 1; j <= n; ++j) {  //从上到下做
                thash[j] = thash[j - 1] * seed + ask(j, i, val);
            }
            for (int j = val; j <= n; ++j) { //才能O(1)得到值
                LL th = thash[j] - po[val] * thash[j - val];
                if (my.has(th)) return true;
                my.toinsert(th);
            }
        }
        return false;
    }
    void work() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i) scanf("%s", str[i] + 1);
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                str_hash[i][j] = str_hash[i][j - 1] * seed + str[i][j];
            }
        }
        int be = 1, en = min(n, m);
        while (be <= en) {
            int mid = (be + en) >> 1;
            if (check(mid)) be = mid + 1;
            else en = mid - 1;
        }
        if (en == 0) {
            printf("%d
    ", en);
            return;
        }
        printf("%d
    ", en);
    //    printf("%d %d
    ", ans1.first, ans1.second);
    //    printf("%d %d
    ", ans1.first + anslen - 1, ans1.second + anslen - 1);
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        po[0] = 1;
        for (int i = 1; i <= maxn - 20; ++i) po[i] = po[i - 1] * seed;
        work();
        return 0;
    }
    View Code
     
  • 相关阅读:
    第三章 运算符与表达式
    python 第二章 对象与类型
    线段树区间染色+注意事项
    ACM-ICPC北京赛区2018重现赛 A题
    删除元组
    修改元组
    访问元组
    Python 元组
    Python List sort()方法
    hdu4501——小明系列故事——买年货(多维背包)
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7445585.html
Copyright © 2020-2023  润新知