AcWing

https://www.acwing.com/problem/content/158/

题意:给一个01矩阵,把它哈希之后,给若干个大小固定的01矩阵,问在不在其中。

讲道理实际上用ull,比1e18还多一点(虽然未必可以取完),首次哈希冲突的期望次数在sqrt(空间),所以就是不可能!

三个ull哈希,被卡内存而削减到只剩一个。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

unordered_set<ull >MAP;

int n, m, a, b;

int g[1005][1005];
ull ha1[1005][1005];
//ull ha2[1005][1005];
//ull ha3[1005][1005];

const ull BASE1 = 23333ll;
//const ull BASE2 = 2333333ll;
//const ull BASE3 = 19260817ll;
const ull BASE12 = 2333388ll;
//const ull BASE22 = 233333388ll;
//const ull BASE32 = 1926081788ll;

ull qpow(ull x, int n) {
    ull res = 1;
    while(n) {
        if(n & 1)
            res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

void init1(int i) {
    ull p1 = qpow(BASE1, b);
//    ull p2 = qpow(BASE2, b);
//    ull p3 = qpow(BASE3, b);

    ull cur1 = 0;
//    ull cur2 = 0;
//    ull cur3 = 0;
    for(int j = 0; j < b; ++j) {
        cur1 = cur1 * BASE1 + g[i][j];
//        cur2 = cur2 * BASE2 + g[i][j];
//        cur3 = cur3 * BASE3 + g[i][j];
    }
    ha1[i][0] = cur1;
//    ha2[i][0] = cur2;
//    ha3[i][0] = cur3;
    for(int j = b; j < m; ++j) {
        cur1 = cur1 * BASE1 + g[i][j];
        cur1 = cur1 - g[i][j - b] * p1;
//        cur2 = cur2 * BASE2 + g[i][j];
//        cur2 = cur2 - g[i][j - b] * p2;
//        cur3 = cur3 * BASE3 + g[i][j];
//        cur3 = cur3 - g[i][j - b] * p3;
        ha1[i][j - b + 1] = cur1;
//        ha2[i][j - b + 1] = cur2;
//        ha3[i][j - b + 1] = cur3;
        /*printf("i=%d j=%d ha1=%llu
", i, j, ha1[i][j - b + 1]);
        printf("i=%d j=%d ha2=%llu
", i, j, ha2[i][j - b + 1]);
        printf("i=%d j=%d ha3=%llu
", i, j, ha2[i][j - b + 1]);
        printf("
");*/
    }
    //printf("
");
}

ull haha1[1005][1005];
//ull haha2[1005][1005];
//ull haha3[1005][1005];

void init2(int j) {
    ull p1 = qpow(BASE12, a);
//    ull p2 = qpow(BASE22, a);
//    ull p3 = qpow(BASE32, a);

    ull cur1 = 0;
//    ull cur2 = 0;
//    ull cur3 = 0;
    for(int i = 0; i < a; ++i) {
        cur1 = cur1 * BASE12 + ha1[i][j];
//        cur2 = cur2 * BASE22 + ha2[i][j];
//        cur3 = cur3 * BASE32 + ha3[i][j];
    }
    haha1[0][j] = cur1;
//    haha2[0][j] = cur2;
//    haha3[0][j] = cur3;
    for(int i = a; i < n; ++i) {
        cur1 = cur1 * BASE12 + ha1[i][j];
        cur1 = cur1 - ha1[i - a][j] * p1;
//        cur2 = cur2 * BASE22 + ha2[i][j];
//        cur2 = cur2 - ha2[i - a][j] * p2;
//        cur3 = cur3 * BASE32 + ha3[i][j];
//        cur3 = cur3 - ha3[i - a][j] * p3;
        haha1[i - a + 1][j] = cur1;
//        haha2[i - a + 1][j] = cur2;
//        haha3[i - a + 1][j] = cur3;
        /*printf("i=%d j=%d haha1=%llu
", i, j, haha1[i][j]);
        printf("i=%d j=%d haha2=%llu
", i, j, haha2[i][j]);
        printf("i=%d j=%d haha3=%llu
", i, j, haha3[i][j]);
        printf("
");*/
    }
    //printf("
");
}

void insert(int si, int sj) {
    ull cur1 = haha1[si][sj];
//    ull cur2 = haha2[si][sj];
//    ull cur3 = haha3[si][sj];
//    MAP[cur1].push_back({cur2, cur3});
    MAP.insert(cur1);
}

bool find() {
    ull cur1 = 0;
//    ull cur2 = 0;
//    ull cur3 = 0;
    int cur;
    for(int i = 0; i < a; ++i) {
        ull tcur1 = 0;
//        ull tcur2 = 0;
//        ull tcur3 = 0;
        for(int j = 0; j < b; ++j) {
            scanf("%1d", &cur);
            //printf("%d", cur);
            tcur1 = tcur1 * BASE1 + cur;
//            tcur2 = tcur2 * BASE2 + cur;
//            tcur3 = tcur3 * BASE3 + cur;
        }
        cur1 = cur1 * BASE12 + tcur1;
//        cur2 = cur2 * BASE22 + tcur2;
//        cur3 = cur3 * BASE32 + tcur3;
        //printf("
");
    }
    /*printf("cur1=%llu
", cur1);
    printf("cur2=%llu
", cur2);
    printf("cur3=%llu
", cur3);*/
    if(MAP.count(cur1)) {
//        vector < pair<ull, ull> >  vec = MAP[cur1];
//        for(auto i : vec) {
//            if(i.first == cur2 && i.second == cur3)
//                return 1;
//        }
        return 1;
    }
    return 0;
}


int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    scanf("%d%d%d%d", &n, &m, &a, &b);
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j)
            scanf("%1d", &g[i][j]);
    }
    for(int i = 0; i < n; ++i)
        init1(i);
    for(int j = 0; j + b  <= m; ++j)
        init2(j);
    for(int i = 0; i + a <= n; ++i) {
        for(int j = 0; j + b <= m; ++j) {
            insert(i, j);
            /*printf("i=%d j=%d haha1=%llu
", i, j, haha1[i][j]);
            printf("i=%d j=%d haha2=%llu
", i, j, haha2[i][j]);
            printf("i=%d j=%d haha3=%llu
", i, j, haha3[i][j]);
            printf("
");*/
        }
        //printf("
");
    }
    int t;
    scanf("%d", &t);
    while(t--) {
        printf("%d
", find());
    }
}

正常的三哈希?原本的模数因为溢出被卡了,重新选了一群质数。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned short ull;

unordered_map<ull, vector<pair<ull, ull> > >MAP;

int n, m, a, b;

int g[1005][1005];
ull ha1[1005][1005];
ull ha2[1005][1005];
ull ha3[1005][1005];

const ull BASE1 = 233ll;
const ull BASE2 = 131ll;
const ull BASE3 = 37ll;
const ull BASE12 = 13ll;
const ull BASE22 = 97ll;
const ull BASE32 = 47ll;

ull qpow(ull x, int n) {
    ull res = 1;
    while(n) {
        if(n & 1)
            res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

void init1(int i) {
    ull p1 = qpow(BASE1, b);
    ull p2 = qpow(BASE2, b);
    ull p3 = qpow(BASE3, b);

    ull cur1 = 0;
    ull cur2 = 0;
    ull cur3 = 0;
    for(int j = 0; j < b; ++j) {
        cur1 = cur1 * BASE1 + g[i][j];
        cur2 = cur2 * BASE2 + g[i][j];
        cur3 = cur3 * BASE3 + g[i][j];
    }
    ha1[i][0] = cur1;
    ha2[i][0] = cur2;
    ha3[i][0] = cur3;
    for(int j = b; j < m; ++j) {
        cur1 = cur1 * BASE1 + g[i][j];
        cur1 = cur1 - g[i][j - b] * p1;
        cur2 = cur2 * BASE2 + g[i][j];
        cur2 = cur2 - g[i][j - b] * p2;
        cur3 = cur3 * BASE3 + g[i][j];
        cur3 = cur3 - g[i][j - b] * p3;
        ha1[i][j - b + 1] = cur1;
        ha2[i][j - b + 1] = cur2;
        ha3[i][j - b + 1] = cur3;
        /*printf("i=%d j=%d ha1=%llu
", i, j, ha1[i][j - b + 1]);
        printf("i=%d j=%d ha2=%llu
", i, j, ha2[i][j - b + 1]);
        printf("i=%d j=%d ha3=%llu
", i, j, ha2[i][j - b + 1]);
        printf("
");*/
    }
    //printf("
");
}

ull haha1[1005][1005];
ull haha2[1005][1005];
ull haha3[1005][1005];

void init2(int j) {
    ull p1 = qpow(BASE12, a);
    ull p2 = qpow(BASE22, a);
    ull p3 = qpow(BASE32, a);

    ull cur1 = 0;
    ull cur2 = 0;
    ull cur3 = 0;
    for(int i = 0; i < a; ++i) {
        cur1 = cur1 * BASE12 + ha1[i][j];
        cur2 = cur2 * BASE22 + ha2[i][j];
        cur3 = cur3 * BASE32 + ha3[i][j];
    }
    haha1[0][j] = cur1;
    haha2[0][j] = cur2;
    haha3[0][j] = cur3;
    for(int i = a; i < n; ++i) {
        cur1 = cur1 * BASE12 + ha1[i][j];
        cur1 = cur1 - ha1[i - a][j] * p1;
        cur2 = cur2 * BASE22 + ha2[i][j];
        cur2 = cur2 - ha2[i - a][j] * p2;
        cur3 = cur3 * BASE32 + ha3[i][j];
        cur3 = cur3 - ha3[i - a][j] * p3;
        haha1[i - a + 1][j] = cur1;
        haha2[i - a + 1][j] = cur2;
        haha3[i - a + 1][j] = cur3;
        /*printf("i=%d j=%d haha1=%llu
", i, j, haha1[i][j]);
        printf("i=%d j=%d haha2=%llu
", i, j, haha2[i][j]);
        printf("i=%d j=%d haha3=%llu
", i, j, haha3[i][j]);
        printf("
");*/
    }
    //printf("
");
}

void insert(int si, int sj) {
    ull cur1 = haha1[si][sj];
    ull cur2 = haha2[si][sj];
    ull cur3 = haha3[si][sj];
    MAP[cur1].push_back({cur2, cur3});
}

bool find() {
    ull cur1 = 0;
    ull cur2 = 0;
    ull cur3 = 0;
    int cur;
    for(int i = 0; i < a; ++i) {
        ull tcur1 = 0;
        ull tcur2 = 0;
        ull tcur3 = 0;
        for(int j = 0; j < b; ++j) {
            scanf("%1d", &cur);
            //printf("%d", cur);
            tcur1 = tcur1 * BASE1 + cur;
            tcur2 = tcur2 * BASE2 + cur;
            tcur3 = tcur3 * BASE3 + cur;
        }
        cur1 = cur1 * BASE12 + tcur1;
        cur2 = cur2 * BASE22 + tcur2;
        cur3 = cur3 * BASE32 + tcur3;
        //printf("
");
    }
    /*printf("cur1=%llu
", cur1);
    printf("cur2=%llu
", cur2);
    printf("cur3=%llu
", cur3);*/
    if(MAP.count(cur1)) {
        vector < pair<ull, ull> >  vec = MAP[cur1];
        for(auto i : vec) {
            if(i.first == cur2 && i.second == cur3)
                return 1;
        }
    }
    return 0;
}


int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    scanf("%d%d%d%d", &n, &m, &a, &b);
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j)
            scanf("%1d", &g[i][j]);
    }
    for(int i = 0; i < n; ++i)
        init1(i);
    for(int j = 0; j + b  <= m; ++j)
        init2(j);
    for(int i = 0; i + a <= n; ++i) {
        for(int j = 0; j + b <= m; ++j) {
            insert(i, j);
            /*printf("i=%d j=%d haha1=%llu
", i, j, haha1[i][j]);
            printf("i=%d j=%d haha2=%llu
", i, j, haha2[i][j]);
            printf("i=%d j=%d haha3=%llu
", i, j, haha3[i][j]);
            printf("
");*/
        }
        //printf("
");
    }
    int t;
    scanf("%d", &t);
    while(t--) {
        printf("%d
", find());
    }
}

实验证明reserve一个填充70%的哈希表可以加速25%左右。
对于一个1e6个元素的哈希表,使用4e9的unsigned int可能足够了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int ull;

unordered_set<ull>MAP;

int n, m, a, b;

int g[1005][1005];
ull ha1[1005][1005];

const ull BASE1 = 23333ll;
const ull BASE12 = 2333388ll;

ull qpow(ull x, int n) {
    ull res = 1;
    while(n) {
        if(n & 1)
            res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

void init1(int i) {
    ull p1 = qpow(BASE1, b);
    ull cur1 = 0;
    for(int j = 0; j < b; ++j) {
        cur1 = cur1 * BASE1 + g[i][j];
    }
    ha1[i][0] = cur1;
    for(int j = b; j < m; ++j) {
        cur1 = cur1 * BASE1 + g[i][j];
        cur1 = cur1 - g[i][j - b] * p1;
        ha1[i][j - b + 1] = cur1;
    }
}

ull haha1[1005][1005];

void init2(int j) {
    ull p1 = qpow(BASE12, a);
    ull cur1 = 0;
    for(int i = 0; i < a; ++i) {
        cur1 = cur1 * BASE12 + ha1[i][j];
    }
    haha1[0][j] = cur1;
    for(int i = a; i < n; ++i) {
        cur1 = cur1 * BASE12 + ha1[i][j];
        cur1 = cur1 - ha1[i - a][j] * p1;
        haha1[i - a + 1][j] = cur1;
    }
}

void insert(int si, int sj) {
    ull cur1 = haha1[si][sj];
    MAP.insert(cur1);
}

bool find() {
    ull cur1 = 0;
    int cur;
    for(int i = 0; i < a; ++i) {
        ull tcur1 = 0;
        for(int j = 0; j < b; ++j) {
            scanf("%1d", &cur);
            tcur1 = tcur1 * BASE1 + cur;
        }
        cur1 = cur1 * BASE12 + tcur1;
    }
    if(MAP.count(cur1))
        return 1;
    return 0;
}


int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    scanf("%d%d%d%d", &n, &m, &a, &b);
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j)
            scanf("%1d", &g[i][j]);
    }
    for(int i = 0; i < n; ++i)
        init1(i);
    for(int j = 0; j + b  <= m; ++j)
        init2(j);

    MAP.reserve(2000000);
    for(int i = 0; i + a <= n; ++i) {
        for(int j = 0; j + b <= m; ++j)
            insert(i, j);
    }
    int t;
    scanf("%d", &t);
    while(t--)
        printf("%d
", find());
}
原文地址:https://www.cnblogs.com/Inko/p/11681412.html