1. 程式人生 > >「SDOI2008」Sandy 的卡片

「SDOI2008」Sandy 的卡片

用第一個串建立字尾自動機。然後別的串在上面跑。從根節點開始。如果當前不能轉移,一直移到slink或者根。如果移到根,能匹配長度變為0,否則變為maxlen[能轉移的點]+1,再轉移。轉移完往slink上跑,它們至少都能匹配maxlen,和當前匹配取最小。注意在任何點上匹配長度不超過它能表示的最大長度。

//#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include 
<vector> #include <iomanip> #include <cstring> #include <map> #include <queue> #include <set> #include <cassert> #include <stack> #include <bitset> #include <fstream> #define mkp make_pair using namespace std; const double EPS=1e-8; typedef
long long lon; const lon SZ=1107,INF=0x7FFFFFFF,mod=1000000007; int cnt,trans[SZ][2010],slink[SZ],maxlen[SZ]; int minlen[SZ],n,arr[SZ],ans[SZ]; //sadcsadsadasdasdsadsadasdasdsadasd //aabba int add(int pre,int cur) { int z=++cnt; int u=pre; for(;u!=-1&&!trans[u][cur];u=slink[u]) { trans[u][cur]
=z; } if(u==-1) { //cout<<"kind: "<<1<<endl; maxlen[z]=maxlen[pre]+1; minlen[z]=1; slink[z]=0; } else { int x=trans[u][cur]; //if(pre==8)cout<<pre<<"here"<<x<<endl; if(maxlen[x]==maxlen[u]+1) { maxlen[z]=maxlen[pre]+1; minlen[z]=maxlen[x]+1; slink[z]=x; } else { int y=++cnt; memcpy(trans[y],trans[x],sizeof(trans[x])); maxlen[y]=maxlen[u]+1; minlen[y]=maxlen[slink[x]]+1; slink[y]=slink[x]; maxlen[x]=maxlen[x]; minlen[x]=maxlen[y]+1; slink[x]=y; maxlen[z]=maxlen[pre]+1; minlen[z]=maxlen[y]+1; slink[z]=y; for(;u!=-1&&trans[u][cur]==x;u=slink[u]) { trans[u][cur]=y; } } } return z; } int maxv[SZ],tmp[SZ]; bool vst[SZ]; void init() { cin>>n; for(int i=0;i<n;++i) { int sz; cin>>sz; for(int i=1;i<=sz;++i)cin>>arr[i]; for(int i=sz;i>=1;--i)arr[i]-=arr[i-1]-1000; if(i==0) { int pre=0; memset(slink,-1,sizeof(slink)); for(int i=2;i<=sz;++i) { pre=add(pre,arr[i]); } for(int i=1;i<=cnt;++i)maxv[i]=INF; } else { memset(vst,0,sizeof(vst)); memset(tmp,0,sizeof(tmp)); int u=0,it=0; for(int i=2;i<=sz;++i) { int cur=arr[i]; for(;u!=-1&&trans[u][cur]==0;u=slink[u]); if(u==-1) { u=0; it=0; } else { it=min(it,maxlen[u]); u=trans[u][cur]; ++it; tmp[u]=max(tmp[u],it); if(!vst[u])++ans[u]; //cout<<"u: "<<u<<" "<<tmp[u]<<endl; vst[u]=1; int w=slink[u]; for(;w!=-1;w=slink[w]) { if(!vst[w])++ans[w],vst[w]=1; tmp[w]=max(tmp[w],min(it,maxlen[w])); } } } for(int i=1;i<=cnt;++i) { //cout<<"tmp[i]: "<<tmp[i]<<endl; maxv[i]=min(maxv[i],tmp[i]); } } } int res=0; for(int i=1;i<=cnt;++i) { //cout<<"i: "<<i<<" "<<ans[i]<<" "<<maxv[i]<<endl; if(ans[i]==n-1&&maxv[i]!=INF) { res=max(res,maxv[i]); } } cout<<res+1<<endl; } void work() { } int main() { //std::ios::sync_with_stdio(0); //freopen("d:\\1.txt","r",stdin); lon casenum; //cin>>casenum; //cout<<casenum<<endl; //for(lon time=1;time<=casenum;++time) //for(lon time=1;cin>>n,n;++time) { init(); work(); } return 0; } /* 3 5 0 0 1 1 1 5 1 0 0 1 1 5 1 0 1 1 1 5 5 1 1 1 1 1 5 1 1 1 1 1 5 1 1 1 1 1 5 1 1 1 1 1 5 1 1 1 1 1 3 8 0 0 1 1 0 0 1 1 8 0 1 1 0 1 0 1 1 8 1 1 1 1 1 0 1 1 3 6 0 0 1 1 0 0 6 0 1 1 0 1 0 6 1 1 1 1 1 0 3 5 0 1 1 0 0 5 1 1 0 1 0 5 1 1 1 1 0 3 4 1 1 0 0 4 1 0 1 0 4 1 1 1 0 3 4 1 1 0 0 4 1 1 1 1 4 1 1 0 1 */