[USACO Dec06]产奶的模式

来源:互联网 发布:医学论文造假 知乎 编辑:程序博客网 时间:2024/04/30 12:21



题目链接 , 求至少重复K次的最长可重叠子串


首先二分答案,然后判断是否存在至少 k 个子串 hash 值相等

时间复杂度: O(N(logN)2)

毕竟 USACO 良心数据,居然不卡自然溢。。。


// cogs 1690#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>#include <vector>#include <utility>#include <stack>#include <queue>#include <iostream>#include <algorithm>template<class Num>void read(Num &x){    char c; int flag = 1;    while((c = getchar()) < '0' || c > '9')        if(c == '-') flag *= -1;    x = c - '0';    while((c = getchar()) >= '0' && c <= '9')        x = (x<<3) + (x<<1) + (c-'0');    x *= flag;    return;}template<class Num>void write(Num x){    if(x < 0) putchar('-'), x = -x;    static char s[20];int sl = 0;    while(x) s[sl++] = x%10 + '0',x /= 10;    if(!sl) {putchar('0');return;}    while(sl) putchar(s[--sl]);}typedef unsigned int uint;typedef unsigned long long ull;const int maxn = 20007;const uint Base = 1000007;const ull Basell = Base + 2;int n, k, a[maxn];uint hash[maxn], move[maxn];ull hashll[maxn], movell[maxn];void init(){    read(n), read(k);    move[0] = movell[0] = 1;    for(int i = 1; i <= n; i++)    {        read(a[i]);        move[i] = move[i - 1]*Base;        hash[i] = hash[i - 1]*Base + a[i];        movell[i] = movell[i - 1]*Basell;        hashll[i] = hashll[i - 1]*Basell + a[i];    }}bool check(int l){    static std::pair<uint,ull> val[maxn];    int tot = n - l + 1;    for(int i = 0; i + l <= n; i++)        val[i + 1] = std::make_pair(hash[i + l] - hash[i]*move[l], hashll[i + l] - hashll[i]*movell[l]);    std::sort(val + 1, val + tot + 1);    for(int i = 1, j = 1; i <= tot; i = j)    {        while(j <= tot && val[j] == val[i]) j++;        if(j - i >= k) return true;    }    return false;}int solve(){    int l = 1, r = n - 1;    if(!check(l)) return l - 1;    if(check(r)) return r;    while(l + 1 != r)    {        int mid = (l + r) >> 1;        if(check(mid)) l = mid;        else r = mid;    }    return l;}int main(){#ifndef ONLINE_JUDGE    freopen("patterns.in","r",stdin);    freopen("patterns.out","w",stdout);#endif    init();    write(solve()); #ifndef ONLINE_JUDGE    fclose(stdin);    fclose(stdout);#endif    return 0;}
0 0