您的位置:首页 > 其它

UVAL 7902 2016ECfinal F - Mr. Panda and Fantastic Beasts

2017-12-04 13:29 369 查看
题意:

给出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 .

Sample Input

3

2

aba

bab

3

qnu

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: