NOIP2017提高A组模拟10.6】Biology

来源:互联网 发布:淘宝商城女装韩版 编辑:程序博客网 时间:2024/05/21 06:03

题目

这里写图片描述

trie

暴力就是对于每个询问的T个字符串
第i个和第i+1个直接个从后暴力枚举每位是否相同,
但这个方法TLE
我们考虑是否可以用更快的方法来求出两个字符串的最长公共后缀。
我们把所有的字符串从后往前扔进trie中,搞个lca就可以了,最长公共后缀就是lca的深度。

#include <cmath>#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <queue>#include <map>const int maxlongint=2147483647;const int mo=1e9+7;const int N=1000105;using namespace std;struct trie{    int a[27],deep;}tr[N];int n,m,ans,rt[N],tot,len,le,g[N][23],lo;char s[N];int lca(int x,int y){    if(tr[x].deep>tr[y].deep) swap(x,y);    for(int j=lo;j>=0;j--)        if(tr[g[y][j]].deep>=tr[x].deep) y=g[y][j];    if(x==y) return tr[x].deep;    for(int j=lo;j>=0;j--)        if(g[y][j]!=g[x][j]) x=g[x][j],y=g[y][j];    return tr[g[x][0]].deep;}int put(int x){    int now=1;    for(int i=x;i>=1;i--)    {        int t=tr[now].a[s[i]-'a'];        if(t) now=t;        else         {            tr[tr[now].a[s[i]-'a']=++tot].deep=tr[now].deep+1,g[tot][0]=now,now=tot;            for(int j=1;j<=lo;j++) g[now][j]=g[g[now][j-1]][j-1];        }    }    return now;}int main(){    scanf("%d%d",&n,&m);    lo=20;    tr[++tot].deep=1;    for(int i=1;i<=n;i++)    {        scanf("%s",s+1);        int len=strlen(s+1);        rt[i]=put(len);    }    for(int i=1;i<=m;i++)    {        int t;        scanf("%d",&t);        if(t==1)        {            scanf("%s",s+1);            int len=strlen(s+1);            rt[++n]=put(len);        }        else        {            int T,TU[12],ans=maxlongint;            scanf("%d",&T);            for(int j=1;j<=T;j++) scanf("%d",&TU[j]);            for(int j=1;j<=T-1;j++) ans=min(lca(rt[TU[j]],rt[TU[j+1]]),ans);            printf("%d\n",ans-1);        }    }}
原创粉丝点击