loj537

另一道hash题

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#define LL long long

using namespace std;

const LL m1 = 999973, m2 = 1000000000 + 9;

char s[5000005];

LL k, tot, ans;

LL h[m1 + 5], h1[5000005], h2[5000005];

struct hash_table
{
    LL cnt, next;
    string s;
}a[5000005];

void add(LL k1, string s)
{
    a[tot].s = s;
    a[tot].cnt = 1;
    a[tot].next = h[k1];
    h[k1] = tot++;
}

void hash(LL k1, string s)
{
    for (LL i = h[k1]; ~i; i = a[i].next)
    {
        if (a[i].s == s)
        {
            a[i].cnt++;
            ans = max(ans, a[i].cnt);
            return;
        } 
    }
    add(k1, s);
}

LL ksm(LL a, LL b, LL mo)
{
    LL base = a, ans = 1;
    while (b)
    {
        if (b & 1)
            ans = (ans * base) % mo;
        base = (base * base) % mo;
        b >>= 1;
    }
    return ans;
}

int main()
{
//    freopen("loj12A.in","r",stdin); 
    scanf("%s", s + 1);
    scanf("%lld", &k);
    tot = 0;
    memset(h, -1, sizeof h);
    LL len = strlen(s + 1);
    h1[0] = h2[0] = 0;
    LL t1 = ksm(131, k, m1);
    for (int i = 1; i <= len; i++)
    {
        h1[i] = (h1[i - 1] * 131 + s[i]) % m1;
    }
    string ns = string(s + 1);
    for (int i = 1; i <= len - k + 1; i++)
    {
        LL k1 = (((h1[i + k - 1] - h1[i - 1] * t1) % m1) + m1) % m1;
        hash(k1, ns.substr(i - 1, k).c_str());
    }
    printf("%lld\n", ans);
    return 0;
}

这题主要的坑点在于我们需要hash的字符串的重复可能性极大,因此无论是多么优秀的映射算法都会出现大量冲突,此时我们需要手动使用原始的方式——传字符串来进行判重。

posted @ 2017-11-08 19:15  yohanlong  阅读(110)  评论(0编辑  收藏