poj3261 Milk Patterns (binary hash +)

Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can’t predict the quality of milk from one day to the next, there are some regular patterns in the daily milk quality.

To perform a rigorous study, he has invented a complex classification scheme by which each milk sample is recorded as an integer between 0 and 1,000,000 inclusive, and has recorded data from a single cow over N (1 ≤ N ≤ 20,000) days. He wishes to find the longest pattern of samples which repeats identically at least K (2 ≤ K ≤ N) times. This may include overlapping patterns – 1 2 3 2 3 2 3 1 repeats 2 3 2 3 twice, for example.

Help Farmer John by finding the longest repeating subsequence in the sequence of samples. It is guaranteed that at least one subsequence is repeated at least K times.

INPUT
Line. 1: Two Space-Separated integers: N and K
Lines 2 ... N +. 1: N integers, One per Line, The Quality of The Milk ON Day I the Appears ON The Ith Line.
The Output
Line. 1: One Integer, The length Which occurs the longest pattern of AT K times Least
the Sample the Input
2. 8
. 1
2
. 3
2
. 3
2
. 3
. 1
the Sample the Output
. 4
to a string of length N, the string substring find all occurrences of k is greater than the length of the longest found that, and output length.
Thinking: There is a prefix and similar ideas (also encountered once before, if the exclusive OR may be similar to a prefix and prefixes to maintain exclusive OR value), represents from 1 to i of the hash substrings used [i] corresponding to the hash value, each sub-string 10 are seen to decimal number, then for a certain substring we can O (1) to obtain the corresponding hash value. Then we only need to enumerate reverse length len, look at the number of times (that is, the number of occurrences corresponding hash value) of the current length of the substring appears there are no more than k, there is an answer to a direct break; then the t. . .
In fact, there is an enumeration of length is monotonic if the enumeration of certain length l is feasible, all less than l are possible, we only need to check the length l of greater than if also We have to meet the conditions. So half the answer should
still do not know if this question card map, I used the map record number of occurrences could not pass TT

//#include<bits/stdc++.h>
#include<map>
#include <algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define mod (1000000007)
#define middle (l+r)>>1
#define SIZE 1000000+5
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
typedef long double ld;
const int inf_max = 0x3f3f3f;
const ll Linf = 9e18;
const int maxn = 2e4+10;
const long double E = 2.7182818;
const double eps=0.0001;
using namespace std;
inline int read()
{
    int f=1,res=0;
    char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { res=res*10+ch-'0' ; ch=getchar(); }
    return f*res;
}
int n,k,ans;
ll a[maxn],Hash[maxn],pval[maxn],cur[maxn];
const ll base = 10;
bool check(int i) {
    for(int l = 1;l <= n - i + 1; ++l) {
        int r = l + i - 1;
        cur[l] = (Hash[r] - (Hash[l - 1] * pval[r + 1 - l] % mod) % mod + mod) % mod;  
    }
    // printf("%d %lld,%lld\n",n - i + 1,cur[1],cur[2]);
    sort(cur + 1,cur + n - i + 2);
    int maxv = 1,cnt = 1;
    ll num = cur[1];
    for(int j = 2;j <= n - i + 1; ++j) {  //统计相同的数出现的次数,取满足条件的最大值
        if(cur[j] != cur[j - 1]) {
            num = cur[j];
            maxv = max(maxv,cnt);
            cnt = 1;
        }
        else ++cnt;
    }
    //printf("cnt=%d\n",cnt);
    maxv = max(maxv,cnt);
    return (maxv >= k);
}
int main()
{
    while(~scanf("%d%d",&n,&k)) {
        ans = 0;
        memset(Hash,0,sizeof(Hash));
        for(int i = 1;i <= n; ++i) {
            scanf("%lld",&a[i]);
        }
        pval[0] = 1;
        for(int i = 1;i <= n; ++i) {
            pval[i] = pval[i - 1] * base % mod;  //预处理一下后面要用的值
            Hash [i] = (Hash[i - 1] * base % mod + a[i]) % mod;
        }
        int L = 1,R = n;
        while(L <= R) {
            int mid = (L + R) >> 1;
            //printf("mid=%d %d\n",mid,check(mid));
            if(check(mid)) {
                ans = mid;
                L = mid + 1;
            }else R = mid - 1;
        }
        printf("%d\n",ans);
    }
    return 0;
}
Published 33 original articles · won praise 14 · views 408

Guess you like

Origin blog.csdn.net/qq_44077455/article/details/104031357