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 }