码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4821 String 字符串哈希

时间:2014-07-21 23:11:04      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:哈希

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821

题意:给出M和L,和一个字符串S。要求找出S的子串中长度为L*M,并且可以分成M段,每段长L,并且M段都不相同的子串个数。

思路:一道字符串哈希题。哈希的方法是BKDRHash,哈希中进制是31,131等素数,(我还以为这是我自己想出来的哈希方法,原来不是,而且进制也不是我选择的26,而是31这样的素数。)

从len-1开始哈希,Hash[i]=Hash[i+1]*SEED+(ss[i]-‘a‘+1)。O(n)内计算出整个长串的哈希值。在其中长为L的子串的哈希值是Hash[i]-Hash[j+L]*K[L]。

由于M*L<=10^5,所以在检索过程中复杂度最多是O(M*L)。比赛中想到了一种O(M*L)的写法,不过姿势不够优美,挂掉了。优美的姿势是用unsigned long long 的map映射每段长度L的哈希值,用P.size()记录共出现了多少种不同哈希值,如果P.size()=M,则出现了一种符合题意的子串。

在哈希过程中unsighed long long 范围是0~18446744073709551615,并且会自动取模,所以在哈希过程中不需要%MOD这样的出现了。

资料:https://www.byvoid.com/blog/string-hash-compare/

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<cstdlib>
#include<queue>
#include<stack>
#include<vector>
#include<ctype.h>
#include<algorithm>
#include<string>
#define PI acos(-1.0)
#define maxn 10005
#define INF 0x7fffffff
#define SEED 31
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
map < ULL , int > P;
ULL Hash[100005];
ULL K[100005];
int main()
{
    int M,L;
    char ss[100005];
    while(scanf("%d%d",&M,&L)!=EOF)
    {
        ULL tt=1;
        scanf("%s",ss);
        int len=strlen(ss);
        ULL res=0;
        Hash[len]=0;
        K[0]=1;
        for(int i=1; i<=L; i++)
            K[i]=K[i-1]*SEED;
        for(int i=len-1; i>=0; i--)
        {
            Hash[i]=Hash[i+1]*SEED+(ss[i]-'a'+1);
        }
        int t=0,aa=0;
        for(int i=0; i<L&&i+M*L<len; i++)
        {
            P.clear();
            for(int j=i; j<M*L+i; j+=L)
            {
                P[Hash[j]-Hash[j+L]*K[L]]++;
            }
            if(P.size()==M)
                aa++;
            for(int j=M*L+i; j<=len-L; j+=L)
            {
                int head= j-M*L;
                P[Hash[head]-Hash[head+L]*K[L]]--;
                if(P[Hash[head]-Hash[head+L]*K[L]]==0)
                    P.erase(Hash[head]-Hash[head+L]*K[L]);
                P[Hash[j]-Hash[j+L]*K[L]]++;
                if(P.size()==M)
                    aa++;
            }
        }
        printf("%d\n",aa);
    }
    return 0;
}


HDU 4821 String 字符串哈希

标签:哈希

原文地址:http://blog.csdn.net/ooooooooe/article/details/38024831

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!