P2463 [SDOI2008]Sandy的卡片[差分+串拼接后缀数组]

P2463 [SDOI2008]Sandy的卡片

套路都差不多,都是差分后二分答案找lcp。只是这题要把多个串拼接起来成为一个大串,中间用某些值域中没有的数字相隔(最好间隔符都不一样想想为什么),排序后在二分答案,开bin桶统计即可(保证单次check复杂度O(N))。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=120000+7;//m<=101不是m<=100大小没算好坑死我了 
 5 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
 6 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
 7 inline int read(){
 8     int f=0,x=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
 9     while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();return f?-x:x;
10 }
11 int a[N],pos[N],bin[N],vis[N],tot;
12 int n,l,x,ans,tmp,mid,L,R=100;
13 
14 int sa[N],h[N],cnt[N],y[N],rk[N],p,m;
15 inline void suffix_sort(){m=5002;
16     for(register int i=1;i<=tot;++i)++cnt[rk[i]=a[i]];
17     for(register int i=1;i<=m;++i)cnt[i]+=cnt[i-1];
18     for(register int i=tot;i;--i)sa[cnt[rk[i]]--]=i;
19     for(register int k=1;k<tot;k<<=1,p=0){
20         for(register int i=tot-k+1;i<=tot;++i)y[++p]=i;
21         for(register int i=1;i<=tot;++i)if(sa[i]>k)y[++p]=sa[i]-k;
22         for(register int i=1;i<=m;++i)cnt[i]=0;
23         for(register int i=1;i<=tot;++i)++cnt[rk[y[i]]];
24         for(register int i=1;i<=m;++i)cnt[i]+=cnt[i-1];
25         for(register int i=tot;i;--i)sa[cnt[rk[y[i]]]--]=y[i];
26         swap(rk,y);rk[sa[1]]=p=1;
27         for(register int i=2;i<=tot;++i)rk[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p:++p;
28         if(p==tot)break;m=p;
29     }p=0;
30     for(register int i=1;i<=tot;h[rk[i]]=p,p?--p:1,++i)while(a[i+p]==a[sa[rk[i]-1]+p]&&++p);
31 }
32 
33 inline int check(int k){
34     for(register int i=1;a[sa[i]]<=4000;++i){
35         if(h[i]<k){while(x)vis[bin[x--]]=0;}
36         if(!vis[pos[sa[i]]])vis[pos[sa[i]]]=1,bin[++x]=pos[sa[i]];
37         if(x==n)return 1;
38     }
39     return 0;
40 }
41 
42 int main(){//freopen("tmp.in","r",stdin);
43     n=read();
44     for(register int i=1;i<=n;++i){
45         l=read();a[++tot]=read();pos[tot]=i;
46         for(register int j=2;j<=l;++j)a[++tot]=read(),a[tot-1]=a[tot]-a[tot-1]+2000,pos[tot]=i;
47         a[tot]=i+4000;
48     }
49     suffix_sort();
50     while(L<=R){
51         mid=L+R>>1;
52         if(check(mid))ans=mid,L=mid+1;
53         else R=mid-1;
54     }
55     printf("%d\n",ans+1);
56     return 0;
57 }

猜你喜欢

转载自www.cnblogs.com/saigyouji-yuyuko/p/10344562.html