• [模板]字符串哈希_自然溢出


    一.可求子串哈希值的字符串哈希:

    对一个字符串进行这样的哈希操作,得到数组hs,hs[i]表示该字符串1~i部分的子串的哈希值.

    利用这个数组可以表示这个字符串任意子串对应的哈希值.

    // (自然溢出)
    char s[1000];                 // 将要进行操作的字符串
    unsigned long long hs[1000], p[1000];    // 注意是unsigned long long, 这两个数组与字符串大小相同
    
    
        scanf("%s", s + 1);
        p[0] = 1;
        int len = strlen(s + 1);
        for (int i = 1; i <= len; i++) {
            hs[i] = hs[i - 1] * 131 + s[i] - 'a' + 1;    // hs[i] 即为字符串s在1~i部分的子串的哈希值,即前缀哈希值,如果有需要的话把这个循环倒着来一遍就可以得到后缀哈希值
            p[i] = p[i - 1] * 131;                        // p[i] 表示131^i
        }
    
        /* 
        采用如下方法表示l到r的子串的哈希值:
        hs[r] - hs[l - 1] * p[r - l + 1];
        若两段字符串的哈希值相等,则视其为相同字符串.这使得比较两端字符串的复杂度为O(1)
         */

    一般来说,我们取p=131或p=13331,此时(自然溢出)Hash产生冲突的概率极低,...

    除了极特殊构造的数据上,上述Hash算法很难产生冲突,一般情况下上述Hash算法完全可以出现在题目的标准解答中.

                                                        ----<<指南>>

    P2957 [USACO09OCT]Barn Echoes G

    重复部分只会出现在一个字符串的后缀和另一个字符串的前缀出现,那么只需要以O(n)枚举重复部分长度即可.注意有两种情况要考虑.

    理论上说,用strcmp可以达到与比较哈希值相同的效果,只是前者实现起来要处理一些细节,并且复杂度最坏情况下达到了O(n).哈希值算法在O(n)预处理后每次比较只需要O(1)时间.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int l1, l2, ans;
    char s1[100], s2[100];
    unsigned long long hs1[100], hs2[100], p[100];
    
    int main() {
        scanf("%s%s", s1 + 1, s2 + 1);
        l1 = strlen(s1 + 1), l2 = strlen(s2 + 1);
        p[0] = 1;
        for (int i = 1; i <= max(l1, l2); i++) {
            hs1[i] = hs1[i - 1] * 131 + s1[i] - 'a' + 1;
            hs2[i] = hs2[i - 1] * 131 + s2[i] - 'a' + 1;
            p[i] = 131 * p[i - 1];
        }
    
        for (int i = 1; i <= l1; i++)
            if (hs1[l1] - hs1[l1 - i] * p[i] == hs2[i])
                ans = i;
        for (int i = ans; i <= l2; i++)
            if (hs2[l2] - hs2[l2 - i] * p[i] == hs1[i])
                ans = i;
        printf("%d
    ", ans);
    
        return 0;
    }
    P2957

    二.全字符串哈希

    有时候只需要判断两个独立的字符串是否相等,就不需要大费周章了.

    char s[1510];
    unsigned long long hs[SIZE];    // 可以存储SIZE个不同的字符串的哈希值
    
    for (int i = 1; i <= n; i++) {
        scanf("%s", s);
    /******计算字符串s的哈希值并存储到hs[i]中******/
    for (int j = 0; s[j]; j++) { hs[i] *= 131; hs[i] += s[j];        // 相当于把字符用ASCII码转化为数字处理,也可以以特定的方式转化,有什么区别不好说 }
    /*****************************************/ }

    P3370 【模板】字符串哈希

    计算有多少个不同的字符串.把所有字符串转化为哈希值进行比较,由于哈希值是一个数字,就可以利用数字的特性比较:排序后逐个检查是否与上一个数字相等.

    #include <algorithm>
    #include <cctype>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int n, ans;
    char s[1510];
    unsigned long long hs[10010];
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%s", s);
            for (int j = 0; s[j]; j++) {
                hs[i] *= 131;
                if (isalpha(s[j]))
                    hs[i] += s[j] - 'a' + 10;
                else
                    hs[i] += s[j] - '0';
            }
        }
    
        sort(hs + 1, hs + 1 + n);
        for (int i = 1; i <= n; i++)
            if (hs[i] != hs[i - 1]) ans++;
        printf("%d
    ", ans);
    
        return 0;
    }
    P3370
  • 相关阅读:
    高并发、高性能、高可用
    性能优化 = 改改代码?
    高级开发必须理解的Java中SPI机制
    java性能优化的50个细节(珍藏版)
    Java API 设计清单
    QString与QByteArray互相转换的方法
    QT 托盘 hover事件捕捉
    qt捕获全局windows消息
    前端开发树形插件带来的烦恼(一)
    靠谱的div引入任何外链内容
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14247874.html
Copyright © 2020-2023  润新知