JZOJ5397. 【NOIP2017提高A组模拟10.6】Biology

来源:互联网 发布:ubuntu命令行更新软件 编辑:程序博客网 时间:2024/05/21 04:21

这里写图片描述

题解

如果我们将全部字符串倒过来,
那么后缀就变成了前缀。

如果用这些倒过来的字符串的建一棵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 998244353using 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');        }    }}
原创粉丝点击