【二分+哈希_别拦我我要哭】POJ 3261 Milk Patterns

提交了整整一页,我恨!TAT


POJ 3261 Milk Patterns 

  • 题意:找到长度为n的串中出现次数为k的最长子串,子串可以有重叠部分。
  • 思路:就很显然的二分+哈希。

但是我为什么交了一页!!!!

  1. 开始直接while里面直接用了快读,死循环了,跑不出来,T了几发,还以为是算法有问题……www
  2. <=被我写成了<   !!!!!!!! 我????
  3. mod = 20007 ?????? 不是质数啊!!!!!!!  qaq,我哭

就这两个我跟你讲,愣死没找出来bug. ……wwww,最后的最后www随便输了一组样例

10 2
1 1 1 1 1 1 1 1 1 1
  • 发现答案不对,于是发现了第二个臭不要脸的bug 
  • 改了还是WA,心态崩了啊。对照网上的代码,有一篇跟我写的差不多,发现没什么问题啊???什么鬼啊。然后就一句一句的对,发现好像mod不一样,于是就改了和他一样的。shit,就过了!然后想了想20007不是质数啊qaq!!!!!!!!我恨
  • 但是后来我又改了mod为小一点的100007,或者1000007,都过不了。就有点诡异。www. 应该是哈希冲突了。
  • 中间还写了双哈希的代码,代码附在了最后,双哈希的话用100007就可,没什么限制。
  • 这是第一道用了没用ull溢出自动取模的写法!!就给我整成了这个样子,我恨…… 

AC CODE 

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 2e4 + 7;
const int mod = 1000000007;
const ll base = 233;
int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}
ll p[maxN], Hash[maxN];
int n, k, arr[maxN];
void pre()
{
    p[0] = 1;
    for(int i = 1; i <= 20000; i ++ ) p[i] = p[i - 1] * base % mod;
}
ll get_hash(int l, int r, ll *g)
{
    return (g[r] - g[l - 1] * p[r - l + 1] % mod + mod) % mod;
}
bool judge(int x)
{
    ll cnt[maxN]; int tot = 0;
    for(int i = 1; i <= n - x + 1; i ++ )
        cnt[tot ++ ] = get_hash(i, i + x - 1, Hash);
    sort(cnt, cnt + tot);
    int ans = 0, num = 1;
    ll tar = cnt[0];
    for(int i = 1; i < tot; i ++ )
    {
        if(tar == cnt[i])
            ++ num;
        else
        {
            tar = cnt[i];
            ans = max(ans, num);
            num = 1;
        }
    }
    ans = max(ans, num);
    return ans >= k;
}
int main()
{
    pre();
    while(~scanf("%d%d", &n, &k))
    {
        for(int i = 0; i < n; i ++ )
            arr[i] = read();
        Hash[0] = 0;
        for(int i = 1; i <= n; i ++ )
            Hash[i] = (Hash[i - 1] * base % mod + (ll)arr[i - 1]) % mod;
        int l = 1, r = n, mid, ans;
        while(r >= l)
        {
            mid = (l + r) >> 1;
            if(judge(mid))
            {
                ans = mid;
                l = mid + 1;
            }
            else
                r = mid - 1;
        }
        printf("%d\n", ans);
    }
    return 0;
}

双哈希AC CODE 

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 2e4 + 7;
const int mod = 100007;
const ll base = 233;
const ll base2 = 131;
int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}
ll p1[maxN], Hash[maxN], p2[maxN], Hash2[maxN];
void pre()
{
    p1[0] = 1;
    for(int i = 1; i <= 20000; i ++ ) p1[i] = p1[i - 1] * base % mod;
}
void pre2()
{
    p2[0] = 1;
    for(int i = 1; i <= 20000; i ++ ) p2[i] = p2[i - 1] * base2 % mod;
}
ll get_hash(int l, int r, ll *p, ll *g)
{
    return (g[r] - g[l - 1] * p[r - l + 1] % mod + mod) % mod;
}
int n, k, arr[maxN];
bool judge(int x)
{
    pair<ll, ll>pi[maxN];
    int cnt = 0;
    for(int i = 1; i <= n - x + 1; i ++ )
    {
        ll fir = get_hash(i, i + x - 1, p1, Hash);
        ll sec = get_hash(i, i + x - 1, p2, Hash2);
        pi[cnt ++ ] = make_pair(fir, sec);
    }
    sort(pi, pi + cnt);
    pair<ll, ll> tar = pi[0];
    int ans = 0, num = 1;
    for(int i = 1; i < cnt; i ++ )
    {
        if(tar.first == pi[i].first && tar.second == pi[i].second)
            num ++;
        else
        {
            tar = pi[i];
            ans = max(ans, num);
            num = 1;
        }
    }
    ans = max(ans, num);
    return ans >= k;
}
int main()
{
    pre(); pre2();
    while(~scanf("%d%d", &n, &k))
    {
        for(int i = 0; i < n; i ++ )
            arr[i] = read();
        Hash[0] = 0;
        for(int i = 1; i <= n; i ++ )
            Hash[i] = (Hash[i - 1] * base % mod + arr[i - 1]) % mod;
        Hash2[0] = 0;
        for(int i = 1; i <= n; i ++ )
            Hash2[i] = (Hash2[i - 1] * base2 % mod + arr[i - 1]) % mod;
        int l = 1, r = n, mid, ans;
        while(r >= l)
        {
            mid = (l + r) >> 1;
            if(judge(mid))
            {
                ans = mid;
                l = mid + 1;
            }
            else
                r = mid - 1;
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值