poj 1743

若序列ai,ai+1,ai+2,ai+k-1,和aj,aj+1,aj+2,..aj+k-1,满足要求,那ai+1-ai==aj+1-aj,以此类推。所以对原序列进行处理,得到有n-1个元素的序列b,bi代表ai+1-ai的值,那么原问题就转化为了不可重叠最长重复子串。二分结果值k,看是否存在两个长度为k的子串相同,并且不重叠。也就是看是否存在一对后缀,这两个后缀的LCP大于等于k,并且编号差值>=k。把根据height数组分组,得到的每组任意两个后缀的LCP>=k,并且是封闭的,任意一对后缀满足LCP大于等于k的后缀都分别属于这几组,即分了类,然后看每一类中是否至少存在一对。即求出每一组中,sa[i]最大值和最小值的差值,看是否>=k,若存在这样的一个分组,则当前k成立,二分下一个k。

 1     #include <iostream>
 2     #include <cstdio>
 3     #include <cstring>
 4     using namespace std;
 5     const int maxn=20000+10;
 6     int num[maxn];
 7     int sa[maxn],t[maxn],t2[maxn],c[maxn],height[maxn],rank[maxn];
 8     int n;
 9     void build_sa(int m,int n,int *s)
10     {
11         int i,*x=t,*y=t2;
12         for(i=1;i<m;i++) c[i]=0;
13         for(i=0;i<n;i++) c[x[i]=s[i]]++;
14         for(i=2;i<m;i++) c[i]+=c[i-1];
15         for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
16         for(int k=1;k<=n;k<<=1)
17         {
18             int p=0;
19             for(i=n-k;i<n;i++) y[p++]=i;
20             for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
21             for(i=1;i<m;i++) c[i]=0;
22             for(i=0;i<n;i++) c[x[y[i]]]++;
23             for(i=2;i<m;i++) c[i]+=c[i-1];
24             for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
25             swap(x,y);
26             p=2;x[sa[0]]=1;
27             for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
28             if(p>n) break;
29             m=p;
30         }
31     }
32     void getHeight(int n)
33     {
34         int i,j,k=0;
35         for(i=0;i<n;i++) rank[sa[i]]=i;
36         for(i=0;i<n;i++)
37         {
38             if(k) k--;
39             if(rank[i])
40             {
41                 int j=sa[rank[i]-1];
42                 while(num[i+k]==num[j+k]) k++;
43                 height[rank[i]]=k;
44             }
45         }
46     }
47     int bsearch(int n)
48     {
49         int low=3,high=n+1,mid,i,maxv,minv;
50         int flag;
51         while(high>low)
52         {
53             flag=0;
54             mid=low+(high-low)/2;
55             maxv=minv=sa[0];
56             for(i=1;i<n;i++)
57             {
58                 if(height[i]>=mid)
59                 {
60                     if(sa[i]>maxv) maxv=sa[i];
61                     if(sa[i]<minv) minv=sa[i];
62                 }
63                 else
64                 {
65                     if((maxv-minv)>=mid)
66                     {
67                         flag=1;
68                         break;
69                     }
70                     maxv=minv=sa[i];
71                 }
72             }
73             if((maxv-minv)>=mid) flag=1;
74             if(flag) low=mid+1;
75             else high=mid;
76         }
77         return (low-1)>3?low:0;
78     }
79     int main()
80     {
81         //freopen("1.txt","r",stdin);
82         while(scanf("%d",&n)&&n)
83         {
84             int i,tem,v;
85             scanf("%d",&tem);
86             for(i=0;i<n-1;i++)
87             {
88                 scanf("%d",&v);
89                 num[i]=v-tem+88;
90                 tem=v;
91             }
92             build_sa(88+88,n-1,num);
93             getHeight(n-1);
94             int ans=bsearch(n-1);
95             printf("%d\n",ans);
96         }
97         return 0;
98     }

 

 

  

posted @ 2013-06-01 00:46  LJ_COME!!!!!  阅读(188)  评论(0)    收藏  举报