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\n",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\n",ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章