• 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());
    }
    
  • 相关阅读:
    如何理解C语言的左结合 和右结合性
    Egg项目使用vscode的debug模式跑单元测试
    为什么要用MongoDB副本集
    理解JS原型和原型链
    防止重复请求攻击
    引擎、编译器和作用域
    闭包原理解析及其应用场景
    树形结构数据完美解决方案
    Excel文件导入导出(基于Nodejs、exceljs)
    架构层面高并发解决方案选择----项目架构模式选择
  • 原文地址:https://www.cnblogs.com/Inko/p/11681412.html
Copyright © 2020-2023  润新知