即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

poj 3261 Milk Patterns(后缀数组,二分)

编程语言 gyhguoge01234 11℃ 0评论

和poj 1743 差不多


也是算法合集之《后缀数组——处理字符串的有力工具》里面的例题。


里面也有思路

#include 
#include 

const int MAXN = 1000010;
int r[MAXN],K,N,sa[MAXN];
int wa[MAXN],wb[MAXN],wv[MAXN],ws[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; i0;
    for(i=0; ifor(i=1; i1];
    for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;
    for(j=1,p=1; p2,m=p)
    {
        for(p=0,i=n-j; ifor(i=0; iif(sa[i]>=j) y[p++]=sa[i]-j;
        for(i=0; ifor(i=0; i0;
        for(i=0; ifor(i=1; i1];
        for(i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];
        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i1],sa[i],j)?p-1:p++;
    }
    return;
}

int rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k=0;
    for(i=1; i<=n; i++) rank[sa[i]]=i;
    for(i=0; ifor(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
    return;
}

bool C(int d)
{
    int cnt = 1;
    for(int i = 2; i <= N; ++i)
    {
        //height[i]是指后缀数组中相邻的两个后缀的最长公共前缀
        //i是指排序后的后缀中第i个后缀
        //如果height[i] < d 就要重新开始计数
        //因为height[i] < d之后如果还有>d的height[i](也就是后边还有height[i]>d)
        //这时的height[i]已经和之前统计过的height[i]不再有长度>=d的公共前缀了
        //所以要重新计数,也就是重新分组
        if(height[i] >= d)
            ++cnt;
        else
            cnt = 1;
        if(cnt >= K)
            return true;
    }
    return false;
}

void solve()
{
    int lb = 1;
    int ub = N;
    while(lb < ub)
    {
        int mid = (lb+ub)/2;
        if(C(mid)) lb = mid+1;
        else ub = mid;
    }
    printf("%d\n",lb-1);
}

int main()
{
    while(scanf("%d %d",&N,&K) != EOF)
    {
        for(int i = 0; i < N; ++i)
            scanf("%d",&r[i]);
        r[N] = 0;
        da(r,sa,N+1,1000005);
        calheight(r,sa,N);
        solve();
    }
    return 0;
}

转载请注明:CodingBlog » poj 3261 Milk Patterns(后缀数组,二分)

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情