​F - Mr. Panda and Fantastic Beasts​

参考:​​[acm/icpc2016ChinaFinal][CodeforcesGym101194] Mr. Panda and Fantastic Beasts 后缀自动机​​

把2~n的串用一个特殊字符串起来,然后对这个新串建后缀自动机,然后用第一个串在这个自动机上进行匹配即可,当失配的时候就跟答案进行比较,取最优解。​​le=len[link[now]]+1​​的意思是让 le 的值为当前节点所表示字符串的最短长度。

// Created by CAD
#include <bits/stdc++.h>
using namespace std;

const int maxn=2e5+5e4+5;
namespace sam{
int len[maxn<<1],link[maxn<<1],Next[maxn<<1][30];
int sz,last;
string ans="",s;
void init(){ //记得初始化
for(int i=0;i<=sz;++i){
len[i]=link[i]=0;
for(int j=0;j<=26;++j)
Next[i][j]=0;
}
sz=last=0;
len[0]=0,link[0]=-1;

}
void insert(char c){ //插入字符
int now=++sz;
len[now]=len[last]+1;
int p=last;
while(~p&&!Next[p][c-'a']){
Next[p][c-'a']=now;
p=link[p];
}
if(p==-1) link[now]=0;
else{
int q=Next[p][c-'a'];
if(len[p]+1==len[q]) link[now]=q;
else{
int clone=++sz;
len[clone]=len[p]+1;
memcpy(Next[clone],Next[q],sizeof(Next[q]));
link[clone]=link[q];
while(~p&&Next[p][c-'a']==q){
Next[p][c-'a']=clone;
p=link[p];
}
link[q]=link[now]=clone;
}
}
last=now;
}
void update(int l,int r){
if(ans.length()>r-l+1||ans=="") ans=s.substr(l,r-l+1);
else if(ans.length()<r-l+1) return ;
else if(ans>s.substr(l,r-l+1))
ans=s.substr(l,r-l+1);
}
int now=0,le=0;
void attempt(char x,int op){
x-='a';
if(Next[now][x])
now=Next[now][x],le=len[link[now]]+1;
else{
while(~now&&!Next[now][x]){
update(op-le,op);
now=link[now];
if(~now) le=len[link[now]]+1;
}
if(now==-1) now=0,le=0;
else now=Next[now][x],le=len[link[now]]+1;
}
}
void solve(){
ans="";
now=le=0;
for(int i=0;i<s.length();++i)
attempt(s[i],i);
}
}

int main() {
int CASE;scanf("%d",&CASE);
for(int _=1;_<=CASE;_++){
sam::init();
int n;scanf("%d",&n);
cin>>sam::s;
for(int i=1;i<=n-1;++i){
string t; cin>>t;
if(i-1) sam::insert('a'+26);
for(auto j:t) sam::insert(j);
}
sam::solve();
printf("Case #%d: ",_);
if(sam::ans=="") printf("Impossible\n");
else cout<<sam::ans<<"\n";
}
return 0;
}

CAD加油!欢迎跟我一起讨论学习算法