題意:ios
給出n個串,求一個最短的第一個串的子串使它不在其餘的n-1個串中出現,如有多個求字典序最小的。數組
Limits: • 1 ≤ T ≤ 42. • 2 ≤ N ≤ 50000. • N ≤ S1 + S2 + · · · + SN ≤ 250000. • the sum of Si in all test cases doesn’t exceed 3 × 106 .spa
Sample Inputcode
3blog
2get
abastring
babit
3io
qnuclass
cvbb
bnu
3
a
aa
aaa
Sample Output
Case #1: aba
Case #2: q
Case #3: Impossible
代碼:
//這麼多串確定要把他們鏈接起來(之間用沒出現的字符隔開)。後綴數組求出heigh數組,答案要求字典序最小因此後綴數組從前向後找便可,每找到 //一個在第一個串中的i位置時,在該位置向前和向後各找到第一個不在第一個串中的j那麼lcp(i,j)必定是i位置和其餘不在第一個串中後綴的 //最長的lcp,那麼這個lcp+1的長度就必定是在其餘串中沒有出現過,要求字典序最小因此要向後擴展一位,而且這個長度不能超出第一個串。 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MAXN=300000; int t,n,sa[MAXN],he[MAXN],ra[MAXN],xx[MAXN],yy[MAXN],buc[MAXN]; char s[MAXN],ch[MAXN]; int len,len1,m; void get_suf() { int *x=xx,*y=yy; for(int i=0;i<m;i++) buc[i]=0; for(int i=0;i<len;i++) buc[x[i]=s[i]]++; for(int i=1;i<m;i++) buc[i]+=buc[i-1]; for(int i=len-1;i>=0;i--) sa[--buc[x[i]]]=i; for(int k=1;k<=len;k<<=1){ int p=0; for(int i=len-1;i>=len-k;i--) y[p++]=i; for(int i=0;i<len;i++) if(sa[i]>=k) y[p++]=sa[i]-k; for(int i=0;i<m;i++) buc[i]=0; for(int i=0;i<len;i++) buc[x[y[i]]]++; for(int i=1;i<m;i++) buc[i]+=buc[i-1]; for(int i=len-1;i>=0;i--) sa[--buc[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(int i=1;i<len;i++){ if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]) x[sa[i]]=p-1; else x[sa[i]]=p++; } if(p>=len) break; m=p; } for(int i=0;i<len;i++) ra[sa[i]]=i; int k=0; for(int i=0;i<len;i++){ if(ra[i]==0) { he[0]=0;continue; } if(k) k--; int j=sa[ra[i]-1]; while(s[i+k]==s[j+k]&&i+k<len&&j+k<len) k++; he[ra[i]]=k; } } void solve() { int ans=len,pos=-1; for(int i=0;i<len;i++){ while(i<len&&sa[i]>=len1) i++; if(i>=len) break; int plcp=he[i]; for(int j=i-1;j>=0;j--){ if(sa[j]>=len1) break; plcp=min(plcp,he[j]); } int slcp=he[i+1]; for(int j=i+1;j<=len;j++){ if(sa[j]>=len1) break; slcp=min(slcp,he[j]); } plcp=max(plcp,slcp); if(plcp<len1-sa[i]){ if(plcp+1<ans){ ans=plcp+1; pos=sa[i]; } } } if(pos==-1) puts("Impossible"); else{ for(int i=0;i<ans;i++) printf("%c",s[i+pos]); puts(""); } } int main() { scanf("%d",&t); for(int cas=1;cas<=t;cas++){ scanf("%d",&n); scanf("%s",s); len=len1=strlen(s); for(int i=2;i<=n;i++){ s[len++]='#'; scanf("%s",s+len); len=strlen(s); } m=200; get_suf(); printf("Case #%d: ",cas); solve(); } return 0; }