hdu 4821 string(哈希)

来源:互联网 发布:苏联解体知乎 编辑:程序博客网 时间:2024/05/29 16:12

点击打开链接


代码:

#include<iostream>#include<string>#include<cstdio>#include<map>#define getHashval(n, l) hv[n] - hv[n+l] * nbase[l]using namespace std;typedef unsigned long long ULL;const int base = 31;ULL hv[100000+1];ULL nbase[100000+1];map<ULL, int> hashmap; // 类型为map,实际当作一个集合来使用int main(){    int m, l, count;    string s;    nbase[0] = 1;    for(int i=1; i<=100000; i++)        nbase[i] = nbase[i-1] * base;    while(scanf("%d%d", &m, &l) != EOF)    {        cin >> s;        count = 0;        int len = (int)s.length();        hv[len] = 0;        for(int i=len-1; i>=0; i--)            hv[i] = hv[i+1] * base + s.at(i);        // 窗口A,长度为m*l,在输入字符串上滑动,每次滑动1个字符,可以看到len-m*l+1个字串        int end = len-m*l;        for(int i=0; i<l && i<=end; i++)        {            hashmap.clear();//哈希值集合初始化:清空            // 将长度为m*l的串,切割为长度为l的m个子串,分别将各个子串的哈希值放入hashmap集合            // map中,map的key是子串的哈希值,map的值是一个计数,即相同哈希值出现n次的话则值为n            for(int j=i; j<i+m*l; j+=l)                hashmap[getHashval(j, l)]++;            if((int)hashmap.size() == m)                count++;            // 窗口B,长度为m*l,开始与窗口A重合,每次向右滑动l个字符,到窗口右边与字符右边对齐为止            // 每滑动一次B窗口,将最左边那长度l子串的哈希值移出hashmap集合,右边子串的哈希值添加到集合            int end2 = len-m*l-l;            for (int j=i; j<=end2; j+=l)            {                ULL temp = getHashval(j, l);                hashmap[temp]--;                if(hashmap[temp] == 0)                    hashmap.erase(temp);                hashmap[getHashval(j+m*l, l)]++;                if((int)hashmap.size() == m)                    count++;            }        }        printf("%d\n",count);    }    return 0;}


原创粉丝点击