1. 程式人生 > >[Sdoi2008]Sandy的卡片

[Sdoi2008]Sandy的卡片

height ans inline eof flag 進行 有一個 out sam

[Sdoi2008]Sandy的卡片

題目

Sandy和Sue的熱衷於收集幹脆面中的卡片。然而,Sue收集卡片是因為卡片上漂亮的人物形象,而Sandy則是為了積攢卡片兌換超炫的人物模型。每一張卡片都由一些數字進行標記,第i張卡片的序列長度為Mi,要想兌換人物模型,首先必須要集夠N張卡片,對於這N張卡片,如果他們都有一個相同的子串長度為k,則可以兌換一個等級為k的人物模型。相同的定義為:兩個子串長度相同且一個串的全部元素加上一個數就會變成另一個串。Sandy的卡片數遠遠小於要求的N,於是Sue決定在Sandy的生日將自己的卡片送給Sandy,在Sue的幫助下,Sandy終於集夠了N張卡片,但是,Sandy並不清楚他可以兌換到哪個等級的人物模型,現在,請你幫助Sandy和Sue,看看他們最高能夠得到哪個等級的人物模型。

INPUT

第一行為一個數N,表示可以兌換人物模型最少需要的卡片數,即Sandy現在有的卡片數
第i+1行到第i+N行每行第一個數為第i張卡片序列的長度Mi,之後j+1到j+1+Mi個數,用空格分隔,分別表示序列中的第j個數 n<=1000,M<=1000,2<=Mi<=101

OUTPUT

一個數k,表示可以獲得的最高等級。

SAMPLE

INPUT

2
2 1 2
3 4 5 9

OUTPUT

2

解題報告

這道題其實挺簡單= =,就是個處理多字符串最長公共字串= =

主要的是如何處理出加上某個數相等的字串

我們想,既然這個串中的每個數加上某個數能變成另一個串,那麽該串中的各個數的差一定對應相等

那麽我們就對差值建$SA$,跑最長公共字串,把$ans$加一即可

技術分享
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 inline int read(){
 6     int sum(0),f(1);
 7     char ch(getchar());
 8     for(;ch<0||ch>9;ch=getchar())
 9         if(ch==-)
10             f=-1
; 11 for(;ch>=0&&ch<=9;sum=sum*10+(ch^48),ch=getchar()); 12 return sum*f; 13 } 14 int T; 15 int len[1005],xl[1005][1005]; 16 int s[105000],bl[105000],cnt; 17 int n,m; 18 int t1[105000],t2[105000],t3[105000],buc[105000]; 19 int sa[105000],rank[105000],height[105000]; 20 inline void Suffix(){ 21 int i,j,k(0),p(0),*x(t1),*y(t2),*t; 22 for(i=0;i<=m;++i)buc[i]=0; 23 for(i=1;i<=n;++i)++buc[x[i]=s[i]]; 24 for(i=1;i<=m;++i)buc[i]+=buc[i-1]; 25 for(i=n;i>=1;--i)sa[buc[x[i]]--]=i; 26 for(j=1;p<n;j<<=1,m=p){ 27 for(p=0,i=n-j+1;i<=n;++i)y[++p]=i; 28 for(i=1;i<=n;++i) 29 if(sa[i]>j) 30 y[++p]=sa[i]-j; 31 for(i=0;i<=m;++i)buc[i]=0; 32 for(i=1;i<=n;++i)t3[i]=x[y[i]]; 33 for(i=1;i<=n;++i)++buc[t3[i]]; 34 for(i=1;i<=m;++i)buc[i]+=buc[i-1]; 35 for(i=n;i>=1;--i)sa[buc[t3[i]]--]=y[i]; 36 for(t=x,x=y,y=t,x[sa[1]]=1,p=1,i=2;i<=n;++i) 37 x[sa[i]]=((y[sa[i]]==y[sa[i-1]])&&(y[sa[i]+j]==y[sa[i-1]+j]))?p:++p; 38 } 39 for(i=1;i<=n;++i)rank[sa[i]]=i; 40 for(i=1;i<=n;height[rank[i++]]=k) 41 for(k?k--:0,j=sa[rank[i]-1];s[i+k]==s[j+k];++k); 42 } 43 int l(0),r(0x7fffffff),mid,ans(0); 44 bool flag[1005]; 45 inline bool check(int x){ 46 int i,j,k; 47 for(i=1;i<=n;++i){ 48 if(height[i]>=x){ 49 for(j=i;j<=n&&height[j]>=x;++j); 50 --j; 51 memset(flag,0,sizeof(flag)); 52 for(k=i-1;k<=j;++k) 53 flag[bl[sa[k]]]=1; 54 for(k=1;k<=T&&flag[k];++k); 55 if(k==T+1) 56 return true; 57 i=j; 58 } 59 } 60 return false; 61 } 62 int main(){ 63 T=read(); 64 for(int i=1;i<=T;++i){ 65 len[i]=read(); 66 r=min(r,len[i]); 67 for(int j=1;j<=len[i];++j){ 68 xl[i][j]=read(); 69 if(j!=1) 70 m=max(xl[i][j]-xl[i][j-1],m); 71 } 72 } 73 for(int i=1;i<=T;++i){ 74 for(int j=2;j<=len[i];++j){ 75 s[++cnt]=xl[i][j]-xl[i][j-1]; 76 bl[cnt]=i; 77 } 78 s[++cnt]=++m; 79 } 80 n=cnt; 81 Suffix(); 82 while(l<=r){ 83 mid=(l+r)>>1; 84 if(check(mid)) 85 ans=mid,l=mid+1; 86 else 87 r=mid-1; 88 } 89 printf("%d",ans+1); 90 }
View Code

[Sdoi2008]Sandy的卡片