BZOJ 2462 [BeiJing2011]矩陣模板(二維hash)

題目鏈接
題意

查詢小矩陣是否在大矩陣出現過,多組查詢,小矩陣大小固定

思路

二維矩陣hash,將所有小矩陣可能值記錄,最後 O(log)O(log) 判斷是否出現過
本題主要整個二維hash模板,模板常數特別大,需要將重複的自行優化

代碼

存模板用超時代碼

#include <bits/stdc++.h>
using namespace std;

#define ull unsigned long long

// 大常數寫法,memset應該沒有必要
const int N = 1005;
const int M = 1005;

struct Hash{
    int a[N][M], n, m;
    static const ull seed1 = 233, seed2 = 1789;
    ull pw1[N], pw2[M], ha[N][M];
    void init(int _n, int _m) { // 傳入大小,下標從1開始的矩陣a
        n = _n;
        m = _m;
        pw1[0] = pw2[0] = 1;
//        memset(ha,0,sizeof(ha));
        for(int i = 1; i <= m; ++i) pw1[i] = seed1*pw1[i-1];
        for(int i = 1; i <= n; ++i) pw2[i] = seed2*pw2[i-1];
        for(int i = 1; i <= n ; ++i)
            for(int j = 1; j <= m; ++j)
                ha[i][j] = ha[i][j-1]*seed1+a[i][j];
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j)
                ha[i][j] += ha[i-1][j]*seed2;
    }
    ull gethash(int x1, int y1, int x2, int y2) { // 傳入左上右下
        --x1;
        --y1;
        return ha[x2][y2] - ha[x1][y2]*pw2[x2-x1] - ha[x2][y1]*pw1[y2-y1] + ha[x1][y1]*pw2[x2-x1]*pw1[y2-y1];
    }
}myhash, tmp;

char s[1005];
set<ull> se;

int main() {
    int n, m, a, b;
    scanf("%d%d%d%d",&n,&m,&a,&b);
    for(int i = 1; i <= n; ++i) {
        scanf("%s",s+1);
        for(int j = 1; j <= m; ++j) myhash.a[i][j] = (s[j] == '1');
    }
    myhash.init(n,m);
    for(int i = a; i <= n; ++i) {
        for(int j = b; j <= m; ++j) {
            se.insert(myhash.gethash(i-a+1,j-b+1,i,j));
        }
    }
    int q;
    for(scanf("%d",&q); q; --q) {
        for(int i = 1; i <= a; ++i) {
            scanf("%s",s+1);
            for(int j = 1; j <= b; ++j) tmp.a[i][j] = (s[j] == '1');
        }
        tmp.init(a,b);
        ull x = tmp.gethash(1,1,a,b);
        if(se.find(x) != se.end()) puts("1");
        else puts("0");
    }
    return 0;
}

ac 代碼

#include <bits/stdc++.h>
using namespace std;

#define ull unsigned long long

const int N = 1005;
const int M = 1005;
static const int seed1 = 131, seed2 = 1789;
int pw1[N], pw2[M], ha[N][M];

int gethash(int x1, int y1, int x2, int y2) { // 傳入左上右下
    --x1;
    --y1;
    return ha[x2][y2] - ha[x1][y2]*pw2[x2-x1] - ha[x2][y1]*pw1[y2-y1] + ha[x1][y1]*pw2[x2-x1]*pw1[y2-y1];
}

char s[1005][1005];
vector<int> v;

int main() {

    int n, m, a, b;
    scanf("%d%d%d%d",&n,&m,&a,&b);
    for(int i = 1; i <= n; ++i) {
        scanf("%s",s[i]+1);
    }
    /*****/
    pw1[0] = pw2[0] = 1;
    for(int i = 1; i <= m; ++i) pw1[i] = seed1*pw1[i-1];
    for(int i = 1; i <= n; ++i) pw2[i] = seed2*pw2[i-1];
    for(int i = 1; i <= n ; ++i)
        for(int j = 1; j <= m; ++j)
            ha[i][j] = ha[i][j-1]*seed1+s[i][j];
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            ha[i][j] += ha[i-1][j]*seed2;
    /*****/
    for(int i = a; i <= n; ++i) {
        for(int j = b; j <= m; ++j) {
            v.push_back(gethash(i-a+1,j-b+1,i,j));
        }
    }
    sort(v.begin(),v.end());
    int q;
    for(scanf("%d",&q); q; --q) {
        for(int i = 1; i <= a; ++i) {
            scanf("%s",s[i]+1);
        }
        for(int i = 1; i <= a ; ++i)
            for(int j = 1; j <= b; ++j)
                ha[i][j] = ha[i][j-1]*seed1+s[i][j];
        for(int i = 1; i <= a; ++i)
            for(int j = 1; j <= b; ++j)
                ha[i][j] += ha[i-1][j]*seed2;
        int x = gethash(1,1,a,b);
        int y = lower_bound(v.begin(),v.end(), x)-v.begin();
        if(v[y] == x) puts("1");
        else puts("0");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章