Biology 题解
Biology 题解
题意简述
初始有\(n\)个字符串,有\(m\)个操作,操作分为两种:
- 插入一个新的字符串,下标递增(\(n+1,n+2,n+3\dots\))。
- 查询\(k\)个字符串\(x_1,x_2,\dots,x_k\)的最长公共后缀长度。
\(N\le50000,M\le100000,2\le T\le10,|S_i|\le10000,\sum|S_i|\le1000000,总字符串数量\le100000\)。

Solution
的确是百年难得一见的水题。
先将字符串反转,变成一个最长公共前缀问题。
暴力是肯定不行的,这个显然要\(\log\)才过得去。
所以使用\(trie\)维护前缀,\(LCA\)查询最长公共前缀。
最长公共前缀的深度就是公共前缀的长度。
Code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
using namespace std;
template<class T>inline void read(T&x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
x*=fu;
}
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
int n,m;
string reverse(string str)
{
for(int i=0;i<str.size()/2;i++)
{
swap(str[i],str[str.size()-i-1]);
}
// cout<<str<<endl;
return str;
}
struct Trie
{
int ch[1000010][26];
int cnt;
int v[100010];//将字符串编号映射到其末尾的节点
int dep[1000010],f[1000010][17];
Trie()
{
cnt=1;
memset(ch,0,sizeof(ch));
memset(v,0,sizeof(v));
}
void insert(string str,int pos)
{
int u=1;
for(int i=0;i<str.size();i++)
{
if(!ch[u][str[i]-'a']) ch[u][str[i]-'a']=++cnt;
dep[ch[u][str[i]-'a']]=dep[u]+1;
f[ch[u][str[i]-'a']][0]=u;
u=ch[u][str[i]-'a'];
for(int i=1;i<=16;i++) f[u][i]=f[f[u][i-1]][i-1];
}
v[pos]=u;
}
int LCA(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=16;i>=0;i--)
{
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
}
if(x==y) return x;
for(int i=16;i>=0;i--)
{
if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
}
return f[x][0];
}
}trie;
int main()
{
// freopen("biology.in","r",stdin);
// freopen("biology.out","w",stdout);
n=read();
m=read();
string t;
for(int i=1;i<=n;i++) cin>>t,trie.insert(reverse(t),i);
int op,x,y;
while(m--)
{
op=read();
if(op==1)
{
cin>>t;
trie.insert(reverse(t),++n);
}
else
{
x=read();
y=trie.v[read()];
for(int i=2;i<=x;i++)
{
y=trie.LCA(y,trie.v[read()]);
}
write(trie.dep[y]);
}
}
return 0;
}
/*
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
*/

浙公网安备 33010602011771号