HDOJ--4821--String【字符串hash】

来源:互联网 发布:长沙网络公关 编辑:程序博客网 时间:2024/06/14 05:29

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

题意:给一个字符串,选m个长度为l的子串组成新的串,要求这m个子串互不相同,问有多少种组合。


字符串hash题目,以前没做过,做这道之前还用bkdrhash做了两道简单的题目,POJ1200和HDU1800。

用base数组记录乘了几个seed,base[i]表示seed^i,这个数组在之后计算子串hash值的时候会用到,先预处理一遍节省时间。

如果字符串从前往后hash,则hash[ i ] - hash[ i - l ] * base[ l ] 就是子串 [ i - l , i ] 的hash值,而从后往前hash的话 hash[ i ] - hash[ i + l ] * base[ l ] 就是子串 [ i , i + l ] 的hash值。

推导过程:以从前往后hash为例。假设字符串abab,子串长度2,则

i = 4时的hash值( ( ( (0+a)*seed+b ) * seed +a ) * seed + b ) ,

i - l = 2的hash值( (0+a)*seed+b ),乘base[2]之后 ( ( ( (0+a)*seed+b ) * seed  ) * seed  )

二者相减为a * seed + b,就是区间 [ i - l, i ] 对应字母 ab 的hash值。

之后按照每一点枚举m个l长度的子串,当他们hash值不同时就是一个结果。


#include<cstring>#include<string>#include<fstream>#include<iostream>#include<iomanip>#include<cstdio>#include<cctype>#include<algorithm>#include<queue>#include<map>#include<set>#include<vector>#include<stack>#include<ctime>#include<cstdlib>#include<functional>#include<cmath>using namespace std;#define PI acos(-1.0)#define MAXN 100010#define eps 1e-7#define INF 0x7FFFFFFF#define seed 131typedef long long ll;typedef unsigned long long ull;char s[MAXN];ull base[MAXN],Hash[MAXN];map<ull,int> mp;int main(){    int m,l,i,len,ans;    base[0] = 1;    for(i=1;i<MAXN;i++) base[i] = base[i-1] * seed;    while(scanf("%d%d",&m,&l)!=EOF){        scanf("%s",s);        ans = 0;        len = strlen(s);        Hash[len] = 0;        for(i=len-1;i>=0;i--){            Hash[i] = Hash[i+1] * seed + s[i] - 'a';        }        for(i=0;i<l&&i+m*l<len;i++){            mp.clear();            for(int j=i;j<i+m*l;j+=l){                ull temp = Hash[j] - Hash[j+l] * base[l];                mp[temp]++;            }            if(mp.size()==m)    ans++;            for(int j=i+m*l;j+l<=len;j+=l){                ull temp = Hash[j-m*l] - Hash[j-(m-1)*l] * base[l];                mp[temp]--;                if(!mp[temp])   mp.erase(temp);                temp = Hash[j] - Hash[j+l] * base[l];                mp[temp]++;                if(mp.size()==m)    ans++;            }        }        printf("%d\n",ans);    }    return 0;}


2 2
原创粉丝点击