zoukankan      html  css  js  c++  java
  • 洛谷P3370 && 字符串哈希讲解

    字符串哈希

    寻找长度为n的主串s中的的匹配串T(长度为m)出现的位置或者次数问题属于字符串匹配问题。

    朴素(一般)的想法就是从一个字符串的头开始for循环查找,当查找的一个字符与匹配串首字符相同时,往后查找长度为匹配串长度的字符串并一一比对,如果都一样的话,那么答案就加一;

    但是往往有些题数据复杂度不允许这么干,于是我们引入字符串哈希这种操作;

    具体流程:

    滚动哈希,是优化复杂度的核心;

    对于一个字符串的哈希值,我们定义哈希函数为H(C)=(c1b^m-1=c2b^m-2....+cmb^0)mod h,

    说明:C为一个字符串名称,它由c1c2c3...cm组成,也就是C=c1c2c3c4....cm,其中m为C的长度;

    b和h为互质的两个数(b<h),

    也就是我们可以把一个字符串看成一个b进制的数(把‘A’看成1,把‘B’看成2...),因为10进制数(such as1234)可以表示成为1*10^3+2*10^2+3*10^1+4,在这里把10换成b就是b进制数的表示方式;因为字符串哈希形成的数可能很大所以要对原数进行取模h。

    很多神仙心中可能会有疑问:取模后即使是不同的字符串他们的哈希值也可能相等,那么不同的字符串会有可能得出相同的哈希值,这样答案不就出错了吗?

    答案是有可能的。算法错误?!

    但是我们可以将可能性降到几乎忽略不计!

    因为 仔细想想,是取模运算使哈希拥有了这种可能,只有取到h和b的公倍数时,哈希值才会相等,

    但是我们把最小公倍数搞的很大,不就取不到了吗?

    那么首先b和h要满足互质,在相近大小下使公倍数尽可能大,然后有意识调高b和h的值,

    如果分别去h=1e9+7,b=1e9+9的话,他们最小公倍数就为1e9+7)*(1e9+9),哈希值相同概率为1/(1e9+7)*(1e9+9),小到没朋友;

    可惜还是有毒瘤小伙伴出毒瘤数据坑害蒟蒻们。。)

    不管了。。反正算法就是这样;

    在代码实现中,h不必专门取1e9+7后再进行手动缩小操作,只要利用unsigned无符号整形的自然溢出特性,即可实现;

    ok!

    安利一个关于scanf读入字符串的小知识:

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define b 97//97是个质数,你也可以取的更大!
    using namespace std;
    int n,a[10001],ans=1;//ans初始值为1,因为后面在判断时会少一个
    char s[10003];
    inline long long hash(char s[]){
        int lenc=strlen(s+1);
        unsigned long long sum[10001];
        sum[0]=0;
        for(int i=1;i<=lenc;i++)
            sum[i]=sum[i-1]*b+(unsigned)(s[i]-'0');//哈希值求法
        return sum[lenc];
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            a[i]=hash(s);//对于每一个字符串求哈希值
        }
        sort(a+1,a+1+n);
        for(int i=2;i<=n;i++)
            if(a[i]!=a[i-1])ans++;    
        printf("%d",ans);
        return 0;
    }

     还有一个惨痛教训:

    这是b开成7后碰到了那极小概率的惨痛经历。。。

    而且测试点太大无法下载。。。

    完结。。

  • 相关阅读:
    完全备份、差异备份以及增量备份的区别(转)
    Backup Exec Inventory 与Catalog的含义(转载)
    从客户端中检测到有潜在危险的Request.Form值的解决办法
    IQueryable与IEnumberable的区别(转)
    SQL递归查询(with cte as) 物料分解
    Http权威指南笔记(二) Http状态码大全
    Http权威指南笔记(一) URI URL URN 关系
    echarts在.Net中使用实例(二) 使用ajax动态加载数据
    echarts在.Net中使用实例(一) 简单的Demo
    sql显示12个月数据
  • 原文地址:https://www.cnblogs.com/lbssxz/p/11031971.html
Copyright © 2011-2022 走看看