题目链接:http://poj.org/problem?id=3261
求可重叠的至少出现K次的最长公共前缀。
先用后缀数组求出height数组,然后二分答案。
1 //STATUS:C++_AC_47MS_720KB 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],ma[1000010]; 32 int n,K,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,ok,mid,ret,cnt; 77 while(l<r){ 78 mid=(l+r)>>1; 79 ok=0;cnt=1; 80 for(i=2;i<=n;i++){ 81 if(height[i]>=mid){ 82 cnt++; 83 } 84 else { 85 if(cnt>=K){ok=1;break;} 86 cnt=1; 87 } 88 } 89 if(cnt>=K)ok=1; 90 if(ok){ret=mid,l=mid+1;} 91 else r=mid; 92 } 93 return ret; 94 } 95 96 97 int main() 98 { 99 // freopen("in.txt","r",stdin); 100 int i,j,hig; 101 while(~scanf("%d%d",&n,&K)) 102 { 103 for(i=0;i<n;i++){ 104 scanf("%d",&num[i]); 105 c[i]=num[i]; 106 } 107 sort(c,c+n); 108 for(i=j=0;i<n;i++){ 109 c[++j]=c[i]; 110 while(c[i]==c[j])i++; 111 i--; 112 } 113 for(i=1;i<=j;i++)ma[c[i]]=i; 114 for(i=0;i<n;i++)num[i]=ma[num[i]]; 115 num[n]=0; 116 m=j+1; 117 118 build_sa(num,n+1,m); 119 getHeight(num,n); 120 121 printf("%d\n",binary(0,n)); 122 } 123 return 0; 124 }