字符串Hash

字符串Hash

就是通过某种方法把一个字符串转换为一个整数,比较时就不用一个一个去比较,但要尽量降低不同字符串这个整数的重合率。

主要应用

寻找长度为n的主串S中的匹配串T(长度为m)出现的位置或次数的问题属于字符串匹配问题,也可以用KMP算法。如果是从主串中每次选出两个子串判断是否匹配问题,还是要用字符串hash求解。

方法

给定一个字符串S=s1s2s3…sn,对于字母x,我们规定idx(x)=x-‘a’+1。(我们也可以直接用si的ASCII值)

公式

hash[i]=hash[i-1]*p+id(s[i])%mod
相当于对2的64次方-1取模(即使用unsigned long long存储可能也会溢出,要取模,还要降低重合率)
p和mod均为质数,且p<mod。

求子串的Hash值

hash[1]=s1
hash[2]=s1 * p+s2
hash[3]=s1 * p ^ 2+s2 * p+s3
hash[4]=s1 * p ^ 3+s2 * p ^ 2+s3 * p+s4
结论:hash=hash[y]-hash[x-1] * p^(y-x+1)(不放心还可以继续取模,通常p取131或1331)

例题:

https://www.acwing.com/problem/content/description/140/

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
unsigned long long h[1000010],p[1000010]; //数组过大放函数外面
char a[1000010];
unsigned long long hash(int x,int y)//递归
{
    unsigned long long s=h[y]-h[x-1]*p[y-x+1];//子串hash公式
    return s;
}
int main()
{
    while(~scanf("%s",a))
    {
        h[0]=0,p[0]=1;
        int n=strlen(a)+1;
        int i;
        for(i=n; i>=0; i--)
            a[i]=a[i-1];
        for(i=1; i<=n; i++)
        {
            h[i]=h[i-1]*131+a[i]-'a'+1;
            p[i]=p[i-1]*131;
        }
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int x1,x2,y1,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            if(hash(x1,y1)==hash(x2,y2))
                printf("Yes\n");
            else
                printf("No\n");
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值