zoukankan      html  css  js  c++  java
  • POJ 3261 可重叠k次最长重复子串

    Milk Patterns
    Time Limit: 5000MS   Memory Limit: 65536K
    Total Submissions: 13127   Accepted: 5842
    Case Time Limit: 2000MS

    Description

    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 appears on the ith line.

    Output

    Line 1: One integer, the length of the longest pattern which occurs at least K times
    /*
    POJ 3261 可重叠k次最长重复子串
    
    给你一串数字,求其中出现k次的最长子串
    
    最开始想的是二分最长长度,然后判断一下是否有k个子串
    但是在判断的时候2b了,并没有判断它们是否是同一个子串,于是乎
    应该进行分组讨论,因为是height中存的是排过序后的最长前缀
    假设height[] = 0 0 1 4 4 4 3 2 4 4
    只有前3个4是同一个子串(排序后一段连续子串是相似的)
    
    所以成了找出height连续大于等于mid的长度sum,判断sum+1是否>=k
    
    hhh-2016-03-11 21:29:00
    */
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <iostream>
    #include <cstring>
    #include <map>
    #include <cstdio>
    #include <vector>
    #include <functional>
    #define lson (i<<1)
    #define rson ((i<<1)|1)
    using namespace std;
    typedef long long ll;
    const int maxn = 100050;
    
    int t1[maxn],t2[maxn],c[maxn];
    bool cmp(int *r,int a,int b,int l)
    {
        return r[a]==r[b] &&r[l+a] == r[l+b];
    }
    
    void get_sa(int str[],int sa[],int Rank[],int height[],int n,int m)
    {
        n++;
        int p,*x=t1,*y=t2;
        for(int i = 0; i < m; i++) c[i] = 0;
        for(int i = 0; i < n; i++) c[x[i] = str[i]]++;
        for(int i = 1; i < m; i++) c[i] += c[i-1];
        for(int i = n-1; i>=0; i--) sa[--c[x[i]]] = i;
        for(int j = 1; j <= n; j <<= 1)
        {
            p = 0;
            for(int i = n-j; i < n; i++) y[p++] = i;
            for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j;
            for(int i = 0; i < m; i++) c[i] = 0;
            for(int i = 0; i < n; i++) c[x[y[i]]]++ ;
            for(int i = 1; i < m; i++) c[i] += c[i-1];
            for(int i = n-1; i >= 0; i--)  sa[--c[x[y[i]]]] = y[i];
    
            swap(x,y);
            p = 1;
            x[sa[0]] = 0;
            for(int i = 1; i < n; i++)
                x[sa[i]] = cmp(y,sa[i-1],sa[i],j)? p-1:p++;
            if(p >= n) break;
            m = p;
        }
        int k = 0;
        n--;
        for(int i = 0; i <= n; i++)
            Rank[sa[i]] = i;
        for(int i = 0; i < n; i++)
        {
            if(k) k--;
            int j = sa[Rank[i]-1];
            while(str[i+k] == str[j+k]) k++;
            height[Rank[i]] = k;
        }
    }
    
    int Rank[maxn],height[maxn];
    int sa[maxn],str[maxn];
    int a[maxn];
    int n;
    
    bool judge(int ans,int k)
    {
        int i =2;
        while(1)
        {
            while(height[i] < ans && i <= n) i++;
            int num = 0;
            if(i > n) break;
            while(height[i] >= ans && i <= n){num++;i++;}
            if(num+1 >= k)return 1;
        }
        return 0;
    }
    map<int,int> mp;
    int main()
    {
        int k,cas = 1;
        while(scanf("%d%d",&n,&k) != EOF)
        {
            int tot = 1,x;
            mp.clear();
            for(int i  = 0; i < n; i++)
            {
                scanf("%d",&x);
                if(!mp[x])
                    mp[x] = tot++;
                a[i] = mp[x];
            }
            a[n] = 0;
    
            get_sa(a,sa,Rank,height,n,n+1);
            int ans = 0;
            int l=1,r=n;
    //        for(int i =2;i <= n;i++)
    //            printf("%d %d
    ",sa[i],height[i]);
    //        cout <<endl;
            while(l <= r)
            {
                int mid = (l+r)>>1;
                if(judge(mid,k))
                {
                    ans = mid;
                    l = mid + 1;
                }
                else
                    r = mid-1;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    

      

    
    
  • 相关阅读:
    Influx Sql系列教程一:database 数据库
    Influx Sql系列教程零:安装及influx-cli使用姿势介绍
    移动端/H5关于cursor:pointer导致的问题
    onselectstart="return false"
    js正则验证之不能使用相同字符
    js通过sessionStorage实现的返回上一页
    MetaHandler.js:移动端适配各种屏幕
    iOS下的 Fixed + Input 调用键盘的时候fixed无效问题解决方案
    js判断三个数字中的最大值
    js判断微信浏览器
  • 原文地址:https://www.cnblogs.com/Przz/p/5409579.html
Copyright © 2011-2022 走看看