双hash板子

我对hash的理解就是可以把一个字符串映射为一个整数,把一个字符串映射为一个整数的方法就是把该字符串里的每种字符看出一个数字,该数字可以由我们规定,也可以由其ascii码决定,例如'a'可以规定其为0,也可以规定其为97,这样还没结束,经过这步操作之后,我们再把这个字符串看为是base进制的数字(对于每道题我们取base时,要大于每一位上的值,例如我们用的十进制数每一位都是小于10的),然后将其转化为10进制的数字,这个数字会爆int,long long,因此需要取模,这样操作完之后就得到了这个字符串对应的整数了。这样对比2个字符串是否相等只用判断对应的2个整数是否相等即可,但是有时候也会出现不同的字符串对应整数相同,这时就需要选择合适的base 和mod或选择多个hash函数。

我下面贴代码里的结构体数组a存的就是hash值,

a[i].hash1,表示的是第i个字符串对应的第一个hash值。

我们在求第i个字符串对应的hash1值时,是通过不断的迭代而来的,先求前1个字符组成的字符串的hash1值,再求前2个,再求前3,一直到字符串结束,就求出了第i个字符串的hash1值,这个过程我并没有保留其前i个字符组成的字符串的hash1值(1<=i<n)如果需要该字符串子串的hash1值的话,就需要弄个hash1数组,hash1[i],表示前i个字符组成的字符串的hash1值。

然后求子串哈希值hash=((hash[r]−hash[l−1]*base^(r−l+1))%mod+mod)%mod

 

#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
#define LL long long
using namespace std;
const LL base1=131;
const LL base2=131;
const LL mod1=1e9+7;
const LL mod2=1e9+9;
char ss[10][10010];
struct node{
    LL hash1,hash2;
}a[10011];
LL make_hash1(char s[])
{
    LL ans=0;
    for(int i=0;i<strlen(s);i++)
     ans=(ans*base1+(LL)(s[i]))%mod1;
    return ans;
}
LL make_hash2(char s[])
{
    LL ans=0;
    for(int i=0;i<strlen(s);i++)
     ans=(ans*base2+(LL)(s[i]))%mod2;
    return ans;
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
     scanf("%s",ss[i]),a[i].hash1=make_hash1(ss[i]),a[i].hash2=make_hash2(ss[i]);

    cout<<"***********"<<endl;
    for(int i=1;i<=n;i++)
    {
        cout<<ss[i]<<"  "<<a[i].hash1<<"   "<<a[i].hash2<<endl;
    }
    return 0;
}//求子串哈希值hash=((hash[r]−hash[l−1]∗mod^(r−l+1))%mod+mod)%mod

 

posted @ 2018-08-09 15:38  eason99  阅读(105)  评论(0编辑  收藏  举报