JZOJ5397. 【NOIP2017提高A组模拟10.6】Biology trie+LCA/哈希

来源:互联网 发布:淘宝卖家关闭佣金 编辑:程序博客网 时间:2024/05/21 04:43

题意:求一些指定串的最长公共后缀,动态加入。

傻逼题,被题意坑了,以为要求最长公共LCS。
hash入门题,二分长度以后判断一下是否所有串都相同。
trie+LCA也可以,不过麻烦一点。
trie+LCA:

#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=1e5+5;const int M=1e6+5;int ch[M][27],pos[N],dep[M],fa[M][21];int val[N],n,m,sz,a[N];char s[M];inline void ins(int num){    int len=strlen(s+1),x=1;    fd(i,len,1)    {        int c=s[i]-'a';        if (!ch[x][c])         {            ch[x][c]=++sz;            dep[sz]=dep[x]+1,fa[sz][0]=x;            fo(j,1,20)fa[sz][j]=fa[fa[sz][j-1]][j-1];        }        x=ch[x][c];    }    pos[num]=x;}inline int lca(int x,int y){    if(dep[x]>dep[y])swap(x,y);     int j=20;    while (dep[x]<dep[y])    {        while (j&&dep[fa[y][j]]<dep[x])j--;        y=fa[y][j];    }    j=20;    while(x!=y)    {        while (j&&fa[x][j]==fa[y][j])j--;        x=fa[x][j],y=fa[y][j];    }    return x;} int main(){    freopen("biology.in","r",stdin);    freopen("biology.out","w",stdout);    scanf("%d%d",&n,&m);    sz=1;    fo(i,1,n)    {        scanf("%s",s+1);        ins(i);    }    fo(i,1,m)    {        int op;        scanf("%d",&op);        if (op==1)        {            scanf("%s",s+1);            ins(++n);        }        else        {            int num,k;            scanf("%d",&num);            fo(j,1,num)            {                int x;                scanf("%d",&x);                if (j==1)k=pos[x];                else k=lca(k,pos[x]);            }            printf("%d\n",dep[k]);        }    }}

hash(更快更短空间更少):

#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int mo=1e9+7;int n,m;const int N=1e6+5;int hash2[N],now,a[15],p[N],q[N];typedef unsigned long long ull;ull hash1[N];char s[N];inline void ins(int i){    scanf("%s",s);    int len=strlen(s);    p[i]=now+1,q[i]=now+len;    fo(j,1,len)     {        now++;        int tmp=s[len-j]-'a'+1;        if (j==1)hash1[now]=hash2[now]=tmp;        else        {            hash1[now]=hash1[now-1]*27+tmp;            hash2[now]=(1ll*hash2[now-1]*27%mo+tmp)%mo;        }    }}inline bool pd(int n,int mid){    int w2=hash2[p[a[1]]+mid-1];    ull w1=hash1[p[a[1]]+mid-1];    fo(i,2,n)        if(hash1[p[a[i]]+mid-1]!=w1||hash2[p[a[i]]+mid-1]!=w2)return 0;    return 1;}inline int solve(int n){    int l=1,r=now,ans=0;    fo(i,1,n)r=min(r,q[a[i]]-p[a[i]]+1);    while (l<=r)    {        int mid=(l+r)>>1;        if (pd(n,mid))l=mid+1,ans=mid;        else r=mid-1;    }    return ans;}int main(){    freopen("biology.in","r",stdin);     freopen("biology.out","w",stdout);     scanf("%d%d",&n,&m);    fo(i,1,n)ins(i);    while (m--)    {        int op;        scanf("%d",&op);        if (op==1)ins(++n);        else        {            int num;            scanf("%d",&num);            fo(i,1,num)scanf("%d",&a[i]);            printf("%d\n",solve(num));        }    }}
原创粉丝点击