poj 3261 Milk Patterns

http://poj.org/problem?id=3261

题意:求一个整数序列最长的重复k次的序列,序列可以重叠。

思路:后缀数组+二分:得到height数组后,二分答案ans,检查height数据里是否有连续的k-1个值不小于ans。

View Code
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<bitset>
#include<string>
#include<climits>
#include<cstdio>
#include<vector>
#include<utility>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define IN puts("in")
#define OUT puts("out")
#define FR(x) freopen(x,"r",stdin)
#define FW(x) freopen(x,"w",stdout)
#define MSET(x,y) memset(x,y,sizeof(x))
#define ST system("pause")
#define NU(x) (x[0]*1000+x[1]*100+x[2]*10+x[3])
using namespace std;
const int maxn = 22005;
int wn[maxn],wa[maxn],wb[maxn],wv[maxn],a[maxn],sa[maxn],Rank[maxn],height[maxn];
char r[maxn];

int cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; }
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x=wa,*y=wb,*t;
    for(i = 0; i < m; ++ i) wn[i] = 0;
    for(i = 0; i < n; ++ i) wn[x[i]=r[i]]++;
    for(i = 1; i < m; ++ i) wn[i] += wn[i-1];
    for(i = n - 1; i >= 0; --i) sa[--wn[x[i]]] = i;
    for(p = 1,j = 1; p < n; j *= 2,m = p)
    {
        for(p = 0,i = n-j; i < n; ++ i) y[p++] =i;
        for(i = 0; i < n; ++ i) if(sa[i]>=j) y[p++] = sa[i] - j;
        for(i = 0; i < m; ++ i) wn[i] = 0;
        for(i = 0; i < n; ++ i) wn[wv[i]=x[y[i]]]++;
        for(i = 1; i < m; ++ i) wn[i] += wn[i-1];
        for(i = n - 1; i >= 0; --i) sa[--wn[wv[i]]] = y[i];
        for(t = x,x = y,y = t,x[sa[0]] = 0,p=1,i=1; i<n; ++i)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    }
}
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1; i <= n; ++ i){ Rank[sa[i]] = i; height[i] = 0;}
    for(i = 0; i < n; height[Rank[i++]]=k)
        for(k?k--:0,j=sa[Rank[i]-1]; r[i+k]==r[j+k];++k);
}
int check(int val,int rep,int n)
{
        int k = 1;
        for(int i = 2; i <= n; ++ i){
                if(height[i]>=val){
                        k++;
                }else{
                        if(k>=rep)return 1;
                        k = 1;
                }
        }
        if(k>=rep)return 1;
        return 0;
}
int main()
{
    int i,j,k,n,m;
    while(scanf("%d %d",&n,&m)==2)
    {
            set<int>mset;
            set<int>::iterator pos;
            map<int,int>mmap;
            for(i = 0; i < n; ++ i){ scanf("%d",a+i); mset.insert(a[i]); }
            pos = mset.begin();
            for(i = 1; pos != mset.end(); ++ pos,++i) mmap[*pos] = i;
            for(i = 0; i < n; ++ i)a[i] = mmap[a[i]];
            a[n] = 0;
            da(a,sa,n+1,mset.size()+3);
            calheight(a,sa,n);
       //     for(i = 1; i <= n; ++ i)printf("%d ",height[i]);puts("");
            int low = 0,high = n,mid;
            k = 0;
            while(low<=high){
                    mid = (low+high) >> 1;
                    if(check(mid,m,n)){
                            low = mid + 1;
                            k = mid;
                    }else high = mid - 1;
            }
            printf("%d\n",k);
    }return 0;
}

posted on 2012-07-09 19:08  aigoruan  阅读(118)  评论(0)    收藏  举报

导航