JZOJ5397. 【NOIP2017提高A组模拟10.6】Biology
程序员文章站
2022-07-14 15:21:29
...
题解
如果我们将全部字符串倒过来,
那么后缀就变成了前缀。
如果用这些倒过来的字符串的建一棵tire,
最长公共前缀就是每一个字符串的最后一个点的lca的深度。
查询就用倍增+lca实现,
对应每加入一个新的节点,就处理一下它的父亲。
code
#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define ll long long
#define N 1000003
#define db double
#define P putchar
#define G getchar
#define mo 998244353
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
ll max(ll a,ll b){return a>b?a:b;}
ll min(ll a,ll b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
struct node
{
int son[26];
}tr[N];
int n,m,f[N][20],deep[N];
int tot,t,k,a[N],x,pos[N];
char s[N];
int lca(int x,int y)
{
if(deep[x]>deep[y])swap(x,y);
for(int j=19;j>=0;j--)
if(deep[x]<=deep[f[y][j]])y=f[y][j];
if(x==y)return x;
for(int j=19;j>=0;j--)
if(f[x][j]!=f[y][j])x=f[x][j],y=f[y][j];
return f[x][0];
}
int ins(char* s,int len)
{
int x=1;
for(int p=1;p<=len;p++)
{
if(tr[x].son[s[p]-'a']==0)
{
deep[++tot]=deep[x]+1;
tr[x].son[s[p]-'a']=tot;
f[tot][0]=x;
for(int j=1;j<20;j++)
f[tot][j]=f[f[tot][j-1]][j-1];
}
x=tr[x].son[s[p]-'a'];
}
return x;
}
int main()
{
freopen("biology.in","r",stdin);
freopen("biology.out","w",stdout);
read(n);read(m);deep[1]=tot=1;
for(int i=1;i<=n;i++)
{
ch=G();
while(ch<'a' || ch>'z')ch=G();x=0;
while('a'<=ch && ch<='z')s[++x]=ch,ch=G();
for(int j=1;j<=x/2;j++)
swap(s[j],s[x-j+1]);
pos[i]=ins(s,x);
}
for(int i=1;i<=m;i++)
{
read(t);
if(t==1)
{
ch=G();
while(ch<'a' || ch>'z')ch=G();x=0;
while('a'<=ch && ch<='z')s[++x]=ch,ch=G();
for(int j=1;j<=x/2;j++)
swap(s[j],s[x-j+1]);
pos[++n]=ins(s,x);
}
else
{
read(k);read(t);t=pos[t];
for(int j=2;j<=k;j++)
read(x),t=lca(t,pos[x]);
write(deep[t]-1),P('\n');
}
}
}
上一篇: 架构师成长之旅第一篇
下一篇: Hadoop入门第一篇——环境配置