题目链接:Fleet of the Eternal Throne
题意:给出
n
个字符串,
题解:注意到如果两个字符串同时匹配到了某一个前缀,那么这个前缀的长度就可以用来更新答案,所以我们可以直接根据前缀建立AC自动机,然后对于每次询问在AC自动机上匹配,用
set
判断是否被匹配过即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 100100;
struct Aho{
int nxt[26],fail,info,len;
void init(){
fill(nxt,nxt+26,0);
fail=info=0;
}
}a[N];
int id,q[N],pre;
void Ist(const string& s){
int now=0,len=s.size();
for(int i=0;i<len;i++){
int t=s[i]-'a';
if(a[now].nxt[t])
now=a[now].nxt[t];
else{
a[++id].init();
a[now].nxt[t]=id;
now=id;
}
a[now].info=++pre;
a[now].len=i+1;
}
}
void Build(){
int now,t,head=0,tail=0;
q[tail++]=0;
a[0].fail=0;
while(head!=tail){
now=q[head++];
for(int i=0;i<26;i++)
if(a[now].nxt[i]){
for(t=a[now].fail;t&&!a[t].nxt[i];t=a[t].fail);
if(now)
a[a[now].nxt[i]].fail=a[t].nxt[i];
q[tail++]=a[now].nxt[i];
}
}
}
int ans;
set<int>f;
string s;
vector<string>v;
void Match(int x,bool op){
int len=v[x].size(),now=0,t,k;
for(int i=0;i<len;i++){
t=v[x][i]-'a';
for(;now&&!a[now].nxt[t];now=a[now].fail);
now=a[now].nxt[t];
for(k=now;k;k=a[k].fail)
if(a[k].info){
if(op)
f.insert(a[k].info);
else{
if(f.find(a[k].info)!=f.end())
ans=max(ans,a[k].len);
}
}
}
}
int main(){
ios::sync_with_stdio(false);
int T,n,m,x,y;
cin>>T;
while(T--){
v.clear();
id=pre=0;
a[0].init();
cin>>n;
for(int i=0;i<n;i++){
cin>>s;
v.push_back(s);
Ist(s);
}
Build();
cin>>m;
while(m--){
cin>>x>>y;
x--,y--;
ans=0;
f.clear();
Match(x,true);
Match(y,false);
printf("%d\n",ans);
}
}
return 0;
}