bzoj 4698 Sandy的卡片 Posted on 2019-05-23 | Views: $SAM$ . 相同的定义比较奇怪,其实只需要差分一下就可以了,问题就是求这些串的最长公共子串.用 $SAM$ 解决. 答案就是求出的公共子串 $+1$ ?但有可能没有位置补,比如 $s_1=”23”,s_2=”23”$ ,答案应该是 $2$ 而不是 $3$ . 解决办法也很简单,在每个串后面加一个独特的且不在字符集中的标识符就可以了. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129#include<bits/stdc++.h>using namespace std;#define ll long longinline int read(){ int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int Siz=1500,MAXN=2e3+10;int buf[MAXN];int L,n,T=0;struct SuffixAutoMation{ int idx,lst; int fa[MAXN],ch[MAXN][Siz]; int len[MAXN],siz[MAXN]; int A[MAXN],t[MAXN]; int mxl[MAXN],res[MAXN]; SuffixAutoMation() { idx=lst=1; } void Extend(int c) { int p=lst,np=++idx; lst=np; res[np]=len[np]=len[p]+1; siz[np]=1; while(p && ch[p][c]==0) ch[p][c]=np,p=fa[p]; if(p==0) fa[np]=1; else { int q=ch[p][c]; if(len[q]==len[p]+1) fa[np]=q; else { int nq=++idx; res[nq]=len[nq]=len[p]+1; fa[nq]=fa[q]; fa[q]=fa[np]=nq; memcpy(ch[nq],ch[q],sizeof ch[q]); while(p && ch[p][c]==q) ch[p][c]=nq,p=fa[p]; } } } void topsort() { for(int i=1; i<=idx; ++i) ++t[len[i]]; for(int i=1; i<=idx; ++i) t[i]+=t[i-1]; for(int i=1; i<=idx; ++i) A[t[len[i]]--]=i; } void solve() { L=read(); for(int i=1; i<=L; ++i) buf[i]=read()-2; buf[L+1]=T+200,buf[L+2]=0; ++L; for(int i=1; i<=L; ++i) buf[i]=buf[i+1]-buf[i]+1200; memset(mxl,0,sizeof mxl); int p=1,tmp=0; for(int i=1; i<=L; ++i) { int c=buf[i]; while(p && ch[p][c]==0) p=fa[p]; if(p==0) p=1,tmp=0; else { tmp=min(tmp,len[p])+1; p=ch[p][c]; } mxl[p]=max(mxl[p],tmp); } for(int i=idx; i>=1; --i) { int u=A[i]; mxl[fa[u]]=max(mxl[fa[u]],mxl[u]); } for(int i=1; i<=idx; ++i) res[i]=min(res[i],mxl[i]); } void pr() { int ans=0; for(int i=1; i<=idx; ++i) ans=max(ans,res[i]); cout<<ans+1<<endl; }} SAM;int main(){ n=read(); L=read(); for(int i=1; i<=L; ++i) buf[i]=read()-2; ++T; buf[L+1]=T+200,buf[L+2]=0; ++L; for(int i=1; i<=L; ++i) { buf[i]=buf[i+1]-buf[i]+1200; SAM.Extend(buf[i]); } SAM.topsort(); for(int i=1; i<n; ++i) { ++T; SAM.solve(); } SAM.pr(); return 0;}