POJ-1743 Musical Theme 后缀数组

  题目链接:http://poj.org/problem?id=1743

     题意:给一些数字串,当做韵律,相同的韵律必须满足:

      1,最少5个数字长;

      2,重复出现的时候,必须相对差值一样,比如{ 1 ,2, 3, 22, 10, 11, 12  },1,2,3与10 11 12是一样的韵律。

      3,韵律不可重叠。

  先用后缀数组处理,然后对height数组二分答案就好了。

  1 //STATUS:C++_AC_266MS_724KB

  2 #include<stdio.h>

  3 #include<stdlib.h>

  4 #include<string.h>

  5 #include<math.h>

  6 #include<iostream>

  7 #include<string>

  8 #include<algorithm>

  9 #include<vector>

 10 #include<queue>

 11 #include<stack>

 12 #include<map>

 13 using namespace std;

 14 #define LL long long

 15 #define pii pair<int,int>

 16 #define Max(a,b) ((a)>(b)?(a):(b))

 17 #define Min(a,b) ((a)<(b)?(a):(b))

 18 #define mem(a,b) memset(a,b,sizeof(a))

 19 #define lson l,mid,rt<<1

 20 #define rson mid+1,r,rt<<1|1

 21 #define PI acos(-1.0)

 22 const int N=20010,INF=0x3f3f3f3f,MOD=10000,STA=8000010;

 23 const LL LNF=0x3f3f3f3f3f3f3f3f;

 24 const double DNF=1e13;

 25 //

 26 void swap(int& a,int& b){int t=a;a=b;b=t;}

 27 void swap(LL& a,LL& b){LL t=a;a=b;b=t;}

 28 //

 29 

 30 int num[N];

 31 int sa[N],t1[N],t2[N],c[N],rank[N],height[N];

 32 int n,m;

 33 

 34 void build_sa(int s[],int n,int m)

 35 {

 36     int i,k,p,*x=t1,*y=t2;

 37     //第一轮基数排序

 38     for(i=0;i<m;i++)c[i]=0;

 39     for(i=0;i<n;i++)c[x[i]=s[i]]++;

 40     for(i=1;i<m;i++)c[i]+=c[i-1];

 41     for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;

 42     for(k=1;k<=n;k<<=1){

 43         p=0;

 44         //直接利用sa数组排序第二关键字

 45         for(i=n-k;i<n;i++)y[p++]=i;

 46         for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;

 47         //基数排序第一关键字

 48         for(i=0;i<m;i++)c[i]=0;

 49         for(i=0;i<n;i++)c[x[y[i]]]++;

 50         for(i=1;i<m;i++)c[i]+=c[i-1];

 51         for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];

 52         //根据sa和x数组计算新的x数组

 53         swap(x,y);

 54         p=1;x[sa[0]]=0;

 55         for(i=1;i<n;i++)

 56             x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;

 57         if(p>=n)break;   //已经排好序,直接退出

 58         m=p;     //下次基数排序的最大值

 59     }

 60 }

 61 

 62 void getHeight(int s[],int n)

 63 {

 64     int i,j,k=0;

 65     for(i=0;i<=n;i++)rank[sa[i]]=i;

 66     for(i=0;i<n;i++){

 67         if(k)k--;

 68         j=sa[rank[i]-1];

 69         while(s[i+k]==s[j+k])k++;

 70         height[rank[i]]=k;

 71     }

 72 }

 73 

 74 int binary(int l,int r)

 75 {

 76     int i,j,mid,low,hig,ok,ret;

 77     while(l<=r){

 78         mid=(l+r)>>1;

 79         ok=0;

 80         low=hig=sa[0];

 81         for(i=2;i<=n;i++){

 82             if(height[i]>=mid){

 83                 if(sa[i]<low)low=sa[i];

 84                 else if(sa[i]>hig)hig=sa[i];

 85             }

 86             else {

 87                 if(hig-low>=mid){ok=1;break;}

 88                 low=hig=sa[i];

 89             }

 90         }

 91         if(hig-low>=mid)ok=1;

 92         if(ok)ret=mid,l=mid+1;

 93         else r=mid-1;

 94     }

 95     if(ret>=4)return ret+1;

 96     return 0;

 97 }

 98 

 99 int main()

100 {

101  //   freopen("in.txt","r",stdin);

102     int i,j,l,r;

103     while(~scanf("%d",&n) && n)

104     {

105         scanf("%d",&l);

106         for(i=1;i<n;i++){

107             scanf("%d",&r);

108             num[i-1]=r-l+88;

109             l=r;

110         }

111         num[--n]=0;

112         m=176;

113         build_sa(num,n+1,m);

114         getHeight(num,n);

115 

116         printf("%d\n",binary(0,n));

117     }

118     return 0;

119 }

 

你可能感兴趣的:(theme)