%%%mikufun他太巨了
你们快去%他啊
SA?我不会啊
这个专题其实有两道题是好久以前做的了,当时的理解非常不深刻,做题也就是各种扔结论。
而被叫去讲了一节课,这回大约是理解一些了。
Sandy的卡片:
$Description:$
Sandy和Sue的热衷于收集干脆面中的卡片。然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型。每一张卡片都由一些数字进行标记,第i张卡片的序列长度为Mi,要想兑换人物模型,首先必须要集够N张卡片,对于这N张卡片,如果他们都有一个相同的子串长度为k,则可以兑换一个等级为k的人物模型。相同的定义为:两个子串长度相同且一个串的全部元素加上一个数就会变成另一个串。Sandy的卡片数远远小于要求的N,于是Sue决定在Sandy的生日将自己的卡片送给Sandy,在Sue的帮助下,Sandy终于集够了N张卡片,但是,Sandy并不清楚他可以兑换到哪个等级的人物模型,现在,请你帮助Sandy和Sue,看看他们最高能够得到哪个等级的人物模型。N<=1000,M<=100
题意明显提示差分。之后问题转化为多串匹配最大长度。
套路:SA处理多串问题就把它们都接起来。
二分答案,$O(NM)check$在连成片的height上查sa,看看是否每个串都出现过。
1 #include<cstdio> 2 #define S 180005 3 int x[S],y[S],c[S],sa[S],s[S],R[1111],rk[S],height[S],cnt,n,al[1111],alc,bl[S],st[S],top,mx=1900,ans,ml,mr=100; 4 void Suffix_Array(int*a,int n,int m){ 5 for(int i=1;i<=m;++i)c[i]=0; 6 for(int i=1;i<=n;++i)x[i]=s[i]+1900; 7 for(int i=1;i<=n;++i)c[x[i]]++; 8 for(int i=1;i<=m;++i)c[i]+=c[i-1]; 9 for(int i=1;i<=n;++i)sa[c[x[i]]--]=i; 10 for(int len=1;n!=m;len<<=1){ 11 int num=0; 12 for(int i=n-len+1;i<=n;++i)y[++num]=i; 13 for(int i=1;i<=n;++i)if(sa[i]>len)y[++num]=sa[i]-len; 14 for(int i=1;i<=m;++i)c[i]=0; 15 for(int i=1;i<=n;++i)c[x[i]]++; 16 for(int i=1;i<=m;++i)c[i]+=c[i-1]; 17 for(int i=n;i;--i)sa[c[x[y[i]]]--]=y[i]; 18 for(int i=1;i<=n;++i)y[i]=x[i],x[i]=0; 19 x[sa[1]]=m=1; 20 for(int i=2;i<=n;++i)x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&y[sa[i]+len]==y[sa[i-1]+len])?m:++m; 21 }for(int i=1;i<=n;++i)rk[sa[i]]=i; 22 for(int i=1,k=0;i<=n;height[rk[i++]]=k,k=k?k-1:k)while(a[i+k]==a[sa[rk[i]-1]+k])k++; 23 } 24 void clear(){while(top)al[st[top--]]=0;alc=0;} 25 bool chk(int len){ 26 for(int i=1;i<=cnt;++i){ 27 if(height[i]<len)clear(); 28 if(!al[bl[sa[i]]]&&sa[i]+len-1<=R[bl[sa[i]]]){ 29 al[bl[sa[i]]]=1;alc++;st[++top]=bl[sa[i]]; 30 if(alc==n)return 1; 31 } 32 }return clear(),0; 33 } 34 void pt(int *a,int n=cnt){for(int i=1;i<=n;++i)printf("%d ",a[i]);puts("");} 35 int main(){ 36 scanf("%d",&n);al[0]=1; 37 for(int i=1,x,l,L;i<=n;++i){ 38 scanf("%d%d",&L,&l); 39 for(int t=2;t<=L;++t)scanf("%d",&x),s[++cnt]=x-l,bl[cnt]=i,l=x; 40 s[++cnt]=++mx;R[i]=cnt-1; 41 }Suffix_Array(s,cnt,4888);//pt(s);pt(rk);pt(height); 42 while(ml<=mr)if(chk(ml+mr>>1))ans=ml=ml+mr>>1,ml++;else mr=(ml+mr>>1)-1; 43 printf("%d\n",ans+1); 44 }