Description
Input
Output
Sample Input
5 5
zzj
pri
prime
ime
owaski
2 3 1 3 5
2 2 2 3
1 actri
2 2 3 4
2 3 2 6 5
Sample Output
0
0
3
1
Solution
简单来说,trie+LCA
复杂详细来说
把那些字符串反着放到一个trie里,记录终点
最后答案就是询问的点的lca的深度
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define N 100100
using namespace std;
int n,ac,k,a[N],t[N*10][26],f[N*10][21],tot=0,deep[N*10];
char s[N];
int lca(int x,int y)
{
if(deep[x]<deep[y]) swap(x,y);
fd(i,20,0) if(deep[f[x][i]]>=deep[y]) x=f[x][i];
fd(i,20,0) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
if(x!=y) x=f[x][0];
return x;
}
int main()
{
freopen("biology.in","r",stdin);
freopen("biology.out","w",stdout);
scanf("%d%d\n",&n,&ac);
deep[1]=1;tot=1;
fo(j,1,n)
{
scanf("%s\n",s+1);
int x=1,m=strlen(s+1);
fd(i,m,1)
{
if(t[x][s[i]-97]==0)
{
t[x][s[i]-97]=++tot,f[tot][0]=x;
deep[tot]=deep[x]+1;
fo(j,1,20) f[tot][j]=f[f[tot][j-1]][j-1];
}
x=t[x][s[i]-97];
}
a[j]=x;
}
for(;ac;ac--)
{
int hzj;scanf("%d ",&hzj);
if(hzj==1)
{
scanf("%s\n",s+1);
int x=1,m=strlen(s+1);
fd(i,m,1)
{
if(t[x][s[i]-97]==0)
{
t[x][s[i]-97]=++tot,f[tot][0]=x;
deep[tot]=deep[x]+1;
fo(j,1,20) f[tot][j]=f[f[tot][j-1]][j-1];
}
x=t[x][s[i]-97];
}
a[++n]=x;
}
else
{
int m,ans=100000,y=0;scanf("%d",&m);
for(;m;m--)
{
int x;scanf("%d",&x);
ans=min(ans,deep[a[x]]-1);
if(y>0) ans=min(ans,deep[lca(a[x],a[y])]-1);
y=x;
}
printf("%d\n",ans);
}
}
}