「luogu2463」[SDOI2008]Sandy的卡片

获得原数列的差分数列,离散化后接在一起,中间用没有出现过的数分隔,于是问题就转化成求这个数列的最长重复子串,且每一段上都至少有一个子串。

求出后缀数组,二分答案即可。

 1 #include<bits/stdc++.h>
 2 #define R register
 3 using namespace std;
 4 const int N=1010,M=1000010,oo=2e9;
 5 int n,m,tot,s[M],a[M],numpos[M];
 6 int x[M<<1],y[M<<1],sa[M<<1],rank[M],h[M],height[M],cnt[M],bel[M];
 7 int cmp(const int xx,const int yy){return a[xx]<a[yy];}
 8 void build(){
 9     for(R int i=1;i<=n;i++) cnt[x[i]]++;
10     for(R int i=2;i<=m;i++) cnt[i]+=cnt[i-1];
11     for(R int i=n;i;i--) sa[cnt[x[i]]--]=i;
12     for(R int i=1;i<=m;i++) cnt[i]=0;
13     for(R int k=1;k<=n;k<<=1){
14         int num=0;
15         for(R int i=n;i>n-k;i--) y[++num]=i;
16         for(R int i=1;i<=n;i++) if(sa[i]>k) y[++num]=sa[i]-k;
17         for(R int i=1;i<=n;i++) cnt[x[i]]++;
18         for(R int i=2;i<=m;i++) cnt[i]+=cnt[i-1];
19         for(R int i=n;i;i--) sa[cnt[x[y[i]]]--]=y[i];
20         for(R int i=1;i<=m;i++) cnt[i]=0;
21         swap(x,y);
22         x[sa[1]]=num=1;
23         for(R int i=2;i<=n;i++){
24             if(y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]) num++;
25             x[sa[i]]=num;
26         }
27         if(num>=n) break;
28         m=num;
29     }
30     for(R int i=1;i<=n;i++) rank[sa[i]]=i;
31     int t=0;
32     for(R int i=1;i<=n;i++){
33         if(t) t--;
34         while(rank[i]-1&&s[i+t]==s[sa[rank[i]-1]+t]) t++;
35         h[i]=t,height[rank[i]]=t;
36     }
37 }
38 bool vis[N];
39 bool check(int k){
40     memset(vis,0,sizeof(vis));
41     vis[0]=1;
42     int minh=oo,cc=0;
43     for(int i=1;i<=n;i++){
44         minh=min(minh,height[i]);
45         if(minh<k){
46             memset(vis,0,sizeof(vis));
47             vis[0]=1;
48             cc=0,minh=oo;
49         }else{
50             if(!vis[bel[sa[i]]]) vis[bel[sa[i]]]=1,cc++;
51             if(i>=1&&!vis[bel[sa[i-1]]]) vis[bel[sa[i-1]]]=1,cc++;
52             if(cc>=tot) return 1;
53         }
54     }
55     return 0;
56 }
57 int main(){
58     int t1,t2,t3,div=1000000000;
59     scanf("%d",&tot);
60     for(R int i=1;i<=tot;i++){
61         scanf("%d%d",&t1,&t2);
62         for(int j=1;j<t1;j++) scanf("%d",&t3),a[++n]=t3-t2,x[n]=a[n],t2=t3,bel[n]=i,numpos[n]=n;
63         a[++n]=++div,numpos[n]=n;
64     }
65     sort(numpos+1,numpos+n+1,cmp);
66     int temp=0;
67     x[numpos[1]]=s[numpos[1]]=++temp;
68     for(int i=2;i<=n;i++){
69         if(a[numpos[i]]!=a[numpos[i-1]]) temp++;
70         s[numpos[i]]=x[numpos[i]]=temp;
71     }
72     m=temp;    
73     build();
74     int l=0,r=n,ans=0;
75     while(l<=r){
76         int mid=(l+r)>>1;
77         if(check(mid)) l=mid+1,ans=mid;
78         else r=mid-1;
79     }
80     printf("%d",ans+1);
81     return 0;
82 }

 

posted @ 2018-03-13 18:29  Cupcake  阅读(92)  评论(0编辑  收藏  举报