zoukankan      html  css  js  c++  java
  • 子串Hash

    模板

    const int N = 1000000 + 16;
    struct Hash {
        const unsigned long long KEY = 137;
        unsigned long long h[N], p[N];
        int len;
        void init(const int a[], int len) {
            this->len = len;
            p[0] = 1;
            for (int i = 1; i <= len; i++)
                p[i] = p[i - 1] * KEY;
            h[len] = 0;
            for (int i = len - 1; i >= 0; i--)
                h[i] = h[i + 1] * KEY + a[i];
        }
        unsigned long long get(int l, int r) {
            return h[l] - h[r + 1] * p[r - l + 1];
        }
        unsigned long long get_for_len(int l, int len) {
            return h[l] - h[l + len] * p[len];
        }
    };
    

    get方法中(0 le l le r < len(a))get_for_len方法中(l in [0, len(a)),len in [1, len(a) - l])

    原理

    (p_i = k^i)
    (h_i = sumlimits_{j in [i, len(a))} a_j cdot k^{j - i})
    (get(l, r) = h_l - h_{r+1} cdot k^{r - l + 1})
    (= sumlimits_{j in [l, len(a))} a_j cdot k^{j - l} - sumlimits_{j in [r+1, len(a))} a_j cdot k^{j-r-1} cdot k^{r-l+1})
    (= sumlimits_{j in [l, len(a))} a_j cdot k^{j - l} - sumlimits_{j in [r+1, len(a))} a_j cdot k^{j-l})
    (= sumlimits_{j in [l, r+1)} a_j cdot k^{j - l} + sumlimits_{j in [r+1, len(a))} a_j cdot k^{j - l} - sumlimits_{j in [r+1, len(a))} a_j cdot k^{j-l})
    (= sumlimits_{j in [l, r+1)} a_j cdot k^{j - l})
    (= sumlimits_{j in [l, r]} a_j cdot k^{j - l})
    在实现的时候用到了unsigned long long的自然溢出,相当于(mod 2^{64})

    例题

    HDU 1711 Number Sequence

    #include <bits/stdc++.h>
    #define DBG(x) cerr << #x << " = " << x << endl
    
    using namespace std;
    
    const int N = 1000000 + 16;
    
    struct Hash {
        const unsigned long long KEY = 137;
        unsigned long long h[N], p[N];
        int len;
        void init(const int a[], int len) {
            this->len = len;
            p[0] = 1;
            for (int i = 1; i <= len; i++)
                p[i] = p[i - 1] * KEY;
            h[len] = 0;
            for (int i = len - 1; i >= 0; i--)
                h[i] = h[i + 1] * KEY + a[i];
        }
        unsigned long long get(int l, int r) {
            return h[l] - h[r + 1] * p[r - l + 1];
        }
        unsigned long long get_for_len(int l, int len) {
            return h[l] - h[l + len] * p[len];
        }
    
    } hp, hs;
    
    int a[N];
    
    int get_ans() {
        for (int i = 0; i + hs.len - 1 < hp.len; i++)
            if (hs.get_for_len(0, hs.len) == hp.get_for_len(i, hs.len))
                return i + 1;
        return -1;
    }
    
    int main(int argc, char **argv) {
        int T;
        scanf("%d", &T);
        while (T--) {
            int n, m;
            scanf("%d%d", &n, &m);
            for (int i = 0; i < n; i++)
                scanf("%d", &a[i]);
            hp.init(a, n);
            for (int i = 0; i < m; i++)
                scanf("%d", &a[i]);
            hs.init(a, m);
            printf("%d
    ", get_ans());
        }
        return 0;
    }
    
    /**
    2
    13 5
    1 2 1 2 3 1 2 3 1 3 2 1 2
    1 2 3 1 3
    13 5
    1 2 1 2 3 1 2 3 1 3 2 1 2
    1 2 3 2 1
    
    6
    -1
    */
    
  • 相关阅读:
    案例53-crm练习修改客户功能实现
    测开之路一百二十五:flask之urlencode参数传递和解析
    测开之路一百二十四:flask之MVC响应过程
    测开之路一百二十三:快速搭建python虚拟环境
    测开之路一百二十二:高级组件之警告框
    测开之路一百二十一:常用组件之助手类
    测开之路一百一二十:常用组件之进度条
    测开之路一百一十九:常用组件之标签和徽章
    测开之路一百一十八:常用组件之面包屑导航和分页导航
    测开之路一百一十七:常用组件之导航栏
  • 原文地址:https://www.cnblogs.com/ToRapture/p/11771173.html
Copyright © 2011-2022 走看看