NOIP2017提高A組模擬10.6】Biology

題目

這裏寫圖片描述

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);
        }
    }
}
發佈了219 篇原創文章 · 獲贊 229 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章