pku 1743

View Code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int maxn = 20005;
int wn[maxn],wa[maxn],wb[maxn],wv[maxn],a[maxn],sa[maxn],rank[maxn],height[maxn];
char r[maxn];
int n;

int Max(int x,int y){return x>y?x:y;}
int Min(int x,int y){return x>y?y:x;}
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 x)
{
    int min = n,max = 0,i;
    for(i = 1; i < n; ++ i)
    {
        if(height[i]<x)
        {
            min = n;
            max = 0;
        }else{
            min = Min(min,sa[i-1]);
            max = Max(max,sa[i-1]);
            min = Min(min,sa[i]);
            max = Max(max,sa[i]);
            if(max-min>x)return 1;
        }
    }return 0;
}
int main()
{
    int i,j,k;
    while(scanf("%d",&n)!=EOF&&n)
    {
        scanf("%d",a+0);
        for(i = 1; i < n; ++ i)
        {
            scanf("%d",a+i);
            a[i-1] = a[i] - a[i-1] + 100;
        }
        a[n-1] = 0;
        da(a,sa,n,256);
        calheight(a,sa,n-1);
        int low = 0,high = n-1,mid;
        while(low<high - 1){
            mid = (low + high)>>1;
            if(check(mid)) low = mid;
            else high = mid;
        }
        if(low>=4)printf("%d\n",low+1);
        else puts("0");
    }return 0;
}

后缀数组

posted on 2012-06-07 12:05  aigoruan  阅读(163)  评论(0)    收藏  举报

导航