Milk Patterns - poj 3261 (求重复k次的最长子串)

题目大意:给你一个数组,求这个数组里面至少重复k次的子串。
 
分析:后缀数组的练手题目...不过给的数字比较大,可以先离散化处理一下即可。
 
代码如下:
===============================================================================================================================
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = 2e4+7;

struct SuffixArr
{
    int tempx[MAXN], tempy[MAXN], text[MAXN], Hash[MAXN];
    int rank[MAXN], sa[MAXN], sum[MAXN], height[MAXN];
    int *x, *y, N, MaxId;

    void GetText(int data[], int len)
    {
        N = len, x=tempx, y=tempy;

        for(int i=0; i<N; i++)
            Hash[i] = data[i];

        sort(Hash, Hash+N);
        MaxId = unique(Hash, Hash+N) - Hash;

        for(int i=0; i<N; i++)
        {
            text[i] = x[i] = lower_bound(Hash, Hash+MaxId, data[i])-Hash;
            y[i] = i;
        }
    }
    bool cmp(int i, int len)
    {
        if(sa[i]+len > N || sa[i-1]+len > N)
            return false;
        if(y[sa[i]]!=y[sa[i-1]] || y[sa[i]+len]!=y[sa[i-1]+len])
            return false;

        return true;
    }
    void BaseSort()
    {
        for(int i=0; i<MaxId; i++)
            sum[i] = 0;
        for(int i=0; i<N; i++)
            sum[ x[ y[i] ] ] += 1;
        for(int i=1; i<MaxId; i++)
            sum[i] += sum[i-1];
        for(int i=N-1; i>=0; i--)
            sa[ --sum[ x[ y[i] ] ] ] = y[i];
    }
    void GetSa()
    {
        BaseSort();

        for(int len=1; len <= N; len<<=1)
        {
            int id = 0;

            for(int i=N-len; i<N; i++)
                y[id++] = i;
            for(int i=0; i<N; i++)if(sa[i] >= len)
                y[id++] = sa[i] - len;

            BaseSort();
            swap(x, y);
            x[ sa[0] ] = id = 0;

            for(int i=1; i<N; i++)
            {
                if(cmp(i, len) == true)
                    x[sa[i]] = id;
                else
                    x[sa[i]] = ++id;
            }

            MaxId = id+1;

            if(MaxId >= N)
                break;
        }
    }
    void GetHeight()
    {
        for(int i=0; i<N; i++)
            rank[sa[i]] = i;

      ///  debug(text);
      ///  debug(rank);

        for(int k=0, i=0; i<N; i++)
        {
            if(!rank[i])
            {
                height[0] = k = 0;
                continue;
            }
            if(k)k--;

            int pre = sa[ rank[i]-1 ];

            while(text[i+k] == text[pre+k])
                k++;
            height[rank[i]] = k;
        }

        ///debug(height);
    }
    void debug(int p[])
    {
        for(int i=0; i<N; i++)
            printf("%d ", p[i]);
        printf("\n");
    }
};

SuffixArr suf;
int data[MAXN];

bool Find(int times, int k)
{
    int cnt=0;

    for(int i=0; i<suf.N; i++)
    {
        if(suf.height[i] < k)
            cnt = 0;
        else
        {
            cnt += 1;
            if(cnt == times-1)
                return true;
        }
    }

    return false;
}

int main()
{
    int N, times;

    while(scanf("%d%d", &N, &times) != EOF)
    {
        for(int i=0; i<N; i++)
            scanf("%d", &data[i]);
        data[N] = -1;

        suf.GetText(data, N+1);
        suf.GetSa();
        suf.GetHeight();

        int L=0, R=N, ans=0;

        while(L <= R)
        {
            int Mid = (L+R)>>1;

            if(Find(times, Mid) == true)
            {
                ans = Mid;
                L = Mid + 1;
            }
            else
                R = Mid - 1;
        }

        printf("%d\n", ans);
    }

    return 0;
}

 

posted @ 2015-09-04 14:39  无忧望月  阅读(102)  评论(0编辑  收藏  举报
levels of contents