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;
}
时间: 2024-10-29 19:09:52

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

POJ 2449 求第K短路

第一道第K短路的题目 QAQ 拿裸的DIJKSTRA + 不断扩展的A* 给2000MS过了 题意:大意是 有N个station 要求从s点到t点 的第k短路 (不过我看题意说的好像是从t到s 可能是出题人写错了) 从这题中还真的学到了很多1.第k短路的算法 A* 还有用边表实现dij (注:以下部份资料来源于网上)所谓A*就是启发是搜索 说白了就是给搜索一个顺序使得搜索更加合理减少无谓的搜索. 如何来确定搜索的顺序?..也就是用一个值来表示 这个值为f[n]..每次搜索取f[x]最小的拓展 那

POJ - 3261 Milk Patterns (后缀数组求可重叠的 k 次最长重复子串)

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 pattern

POJ 3261 Milk Patterns 后缀数组求 一个串种 最长可重复子串重复至少k次

Milk Patterns 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 r

POJ 3261 Milk Patterns 可重复k次的最长重复子串

Milk PatternsTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=3261 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 c

poj 3261 求可重叠的k次最长重复子串

题意:求可重叠的k次最长重复子串的长度 链接:点我 和poj1743差不多 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000

POJ 3261 出现至少K次的可重叠最长子串

题意就是给一列数字,求最长的一个子串,并且满足子串在原数串中出现至少K次,子串可以重叠. 解法是将问题转为判定性问题,二分子串的长度,判定是否满足重复至少K次.判定方法是经典的根据子串长度将Height数组分组,看某一分组是否至少含有K个元素. 1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h

FOJ 题目 2075 Substring (后缀数组求出现k次的最小字典序子串)

Problem 2075 Substring Accept: 70    Submit: 236 Time Limit: 1000 mSec    Memory Limit : 65536 KB Problem Description Given a string, find a substring of it which the original string contains exactly n such substrings. Input There are several cases.

POJ 2774 求两个串的最长公共前缀 | 后缀数组

#include<cstdio> #include<algorithm> #include<cstring> #define N 200005 using namespace std; int buf1[N],buf2[N],sa[N],rnk[N],buc[N],n,height[N],ans,belong[N]; char s[N]; void suffix_sort() { int *x=buf1,*y=buf2,m=1000; for (int i=0;i<

POJ 3261 Milk Patterns

Milk Patterns Time Limit: 5000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: 326164-bit integer IO format: %lld      Java class name: Main Farmer John has noticed that the quality of milk given by his cows varies from day t