HDU 4821 (哈希)

来源:互联网 发布:泰捷网络电视机顶盒 编辑:程序博客网 时间:2024/06/16 20:29

题目链接:点击打开链接

题意:求一个字符串中子串的个数,子串满足:

长度是n*m,并且m个子串分割成的n个串都不同.

知道了一个串的哈希值以后向后递推,然后每次枚举开头的点.

#include <bits/stdc++.h>using namespace std;#define seed 131typedef unsigned long long ull;#define maxn 111111int n, m;char s[maxn];#define pow Pow#define hash Hashull pow[maxn], hash[maxn], bas = 31;map <ull, int> mp;int main () {    //freopen ("in.txt", "r", stdin);    pow[0] = 1;    for (int i = 1; i < maxn; i++)pow[i] = pow[i-1]*bas;    while (cin >> n >> m) {        scanf ("%s", s);        int slen = strlen(s);        hash[slen] = 0;        for (int i = slen-1; i >= 0; i--)            hash[i] = hash[i+1]*bas+s[i]-'a'+1;        int ans = 0;        ull cur;        for (int i = 0; i < m && i+n*m<=slen; i++) {            mp.clear();            for (int j = i; j < i+n*m; j+=m) {            mp[ hash[j] - hash[j+m]*pow[m] ] ++;            }            ans += (mp.size() == n);            for (int j = i+n*m; j+m <= slen; j+=m) {            ull tmp = hash[j-n*m] - hash[j-(n-1)*m]*pow[m];            mp[tmp] --;            if (mp[tmp]==0)                    mp.erase(tmp);            tmp = hash[j] - hash[j+m]*pow[m];            mp[tmp]++;            ans += (mp.size() == n);            }        }        cout << ans << endl;    }    return 0;}/*3 3abcabcbcaabc2 2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab*/


0 0
原创粉丝点击